Search in sources :

Example 11 with SignedJWTInfo

use of org.wso2.carbon.apimgt.impl.jwt.SignedJWTInfo in project carbon-apimgt by wso2.

the class JWTValidator method validateTokenForWS.

/**
 * Validates token for Websocket requests.
 *
 * @param signedJWTInfo  SignedJWT Info
 * @param tokenSignature Token Signature
 * @param jti            JTI
 * @return JWT Validation Info
 * @throws APISecurityException If an error occurs
 */
private JWTValidationInfo validateTokenForWS(SignedJWTInfo signedJWTInfo, String tokenSignature, String jti) throws APISecurityException {
    JWTValidationInfo jwtValidationInfo;
    String jwtHeader = signedJWTInfo.getSignedJWT().getHeader().toString();
    jwtValidationInfo = getJwtValidationInfo(signedJWTInfo, jti);
    if (RevokedJWTDataHolder.isJWTTokenSignatureExistsInRevokedMap(tokenSignature)) {
        if (log.isDebugEnabled()) {
            log.debug("Token retrieved from the revoked jwt token map. Token: " + GatewayUtils.getMaskedToken(jwtHeader));
        }
        log.error("Invalid JWT token. " + GatewayUtils.getMaskedToken(jwtHeader));
        jwtValidationInfo.setValidationCode(APISecurityConstants.API_AUTH_INVALID_CREDENTIALS);
        jwtValidationInfo.setValid(false);
    }
    return jwtValidationInfo;
}
Also used : JWTValidationInfo(org.wso2.carbon.apimgt.common.gateway.dto.JWTValidationInfo)

Example 12 with SignedJWTInfo

use of org.wso2.carbon.apimgt.impl.jwt.SignedJWTInfo in project carbon-apimgt by wso2.

the class JWTValidator method validateScopesForGraphQLSubscriptions.

/**
 * Validate scopes for GraphQL subscription API calls using token scopes in authentication context.
 *
 * @param apiContext            API Context
 * @param apiVersion            API Version
 * @param matchingResource      Matching resource
 * @param jwtToken              JWT Token
 * @param authenticationContext AuthenticationContext
 * @throws APISecurityException if an error occurs
 */
public void validateScopesForGraphQLSubscriptions(String apiContext, String apiVersion, String matchingResource, SignedJWTInfo jwtToken, AuthenticationContext authenticationContext) throws APISecurityException {
    String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
    // Generate TokenValidationContext
    TokenValidationContext tokenValidationContext = new TokenValidationContext();
    APIKeyValidationInfoDTO apiKeyValidationInfoDTO = new APIKeyValidationInfoDTO();
    Set<String> scopeSet = new HashSet<>();
    scopeSet.addAll(authenticationContext.getRequestTokenScopes());
    apiKeyValidationInfoDTO.setScopes(scopeSet);
    tokenValidationContext.setValidationInfoDTO(apiKeyValidationInfoDTO);
    tokenValidationContext.setAccessToken(jwtToken.getToken());
    tokenValidationContext.setHttpVerb(GraphQLConstants.SubscriptionConstants.HTTP_METHOD_NAME);
    tokenValidationContext.setMatchingResource(matchingResource);
    tokenValidationContext.setContext(apiContext);
    tokenValidationContext.setVersion(apiVersion);
    boolean valid = this.apiKeyValidator.validateScopes(tokenValidationContext, tenantDomain);
    if (valid) {
        if (log.isDebugEnabled()) {
            log.debug("Scope validation successful for the resource: " + matchingResource + ", user: " + authenticationContext.getUsername());
        }
    } else {
        String message = "User is NOT authorized to access the Resource: " + matchingResource + ". Scope validation failed.";
        log.debug(message);
        throw new APISecurityException(APISecurityConstants.INVALID_SCOPE, message);
    }
}
Also used : APISecurityException(org.wso2.carbon.apimgt.gateway.handlers.security.APISecurityException) TokenValidationContext(org.wso2.carbon.apimgt.keymgt.service.TokenValidationContext) APIKeyValidationInfoDTO(org.wso2.carbon.apimgt.impl.dto.APIKeyValidationInfoDTO) HashSet(java.util.HashSet)

Example 13 with SignedJWTInfo

use of org.wso2.carbon.apimgt.impl.jwt.SignedJWTInfo in project carbon-apimgt by wso2.

the class JWTValidator method authenticate.

/**
 * Authenticates the given request with a JWT token to see if an API consumer is allowed to access
 * a particular API or not.
 *
 * @param signedJWTInfo The JWT token sent with the API request
 * @param synCtx   The message to be authenticated
 * @return an AuthenticationContext object which contains the authentication information
 * @throws APISecurityException in case of authentication failure
 */
@MethodStats
public AuthenticationContext authenticate(SignedJWTInfo signedJWTInfo, MessageContext synCtx) throws APISecurityException {
    String apiContext = (String) synCtx.getProperty(RESTConstants.REST_API_CONTEXT);
    String apiVersion = (String) synCtx.getProperty(RESTConstants.SYNAPSE_REST_API_VERSION);
    org.apache.axis2.context.MessageContext axis2MsgContext = ((Axis2MessageContext) synCtx).getAxis2MessageContext();
    String httpMethod = (String) axis2MsgContext.getProperty(Constants.Configuration.HTTP_METHOD);
    String matchingResource = (String) synCtx.getProperty(APIConstants.API_ELECTED_RESOURCE);
    String jwtTokenIdentifier = getJWTTokenIdentifier(signedJWTInfo);
    String jwtHeader = signedJWTInfo.getSignedJWT().getHeader().toString();
    try {
        X509Certificate clientCertificate = Utils.getClientCertificate(axis2MsgContext);
        signedJWTInfo.setX509ClientCertificate(clientCertificate);
    } catch (APIManagementException e) {
        log.error("Error while obtaining client certificate. " + GatewayUtils.getMaskedToken(jwtHeader));
    }
    if (StringUtils.isNotEmpty(jwtTokenIdentifier)) {
        if (RevokedJWTDataHolder.isJWTTokenSignatureExistsInRevokedMap(jwtTokenIdentifier)) {
            if (log.isDebugEnabled()) {
                log.debug("Token retrieved from the revoked jwt token map. Token: " + GatewayUtils.getMaskedToken(jwtHeader));
            }
            log.error("Invalid JWT token. " + GatewayUtils.getMaskedToken(jwtHeader));
            throw new APISecurityException(APISecurityConstants.API_AUTH_INVALID_CREDENTIALS, "Invalid JWT token");
        }
    }
    JWTValidationInfo jwtValidationInfo = getJwtValidationInfo(signedJWTInfo, jwtTokenIdentifier);
    if (jwtValidationInfo != null) {
        if (jwtValidationInfo.isValid()) {
            // Validate subscriptions
            APIKeyValidationInfoDTO apiKeyValidationInfoDTO;
            log.debug("Begin subscription validation via Key Manager: " + jwtValidationInfo.getKeyManager());
            apiKeyValidationInfoDTO = validateSubscriptionUsingKeyManager(synCtx, jwtValidationInfo);
            if (log.isDebugEnabled()) {
                log.debug("Subscription validation via Key Manager. Status: " + apiKeyValidationInfoDTO.isAuthorized());
            }
            if (!apiKeyValidationInfoDTO.isAuthorized()) {
                log.debug("User is NOT authorized to access the Resource. API Subscription validation failed.");
                throw new APISecurityException(apiKeyValidationInfoDTO.getValidationStatus(), "User is NOT authorized to access the Resource. API Subscription validation failed.");
            }
            // Validate scopes
            validateScopes(apiContext, apiVersion, matchingResource, httpMethod, jwtValidationInfo, signedJWTInfo);
            synCtx.setProperty(APIMgtGatewayConstants.SCOPES, jwtValidationInfo.getScopes().toString());
            if (apiKeyValidationInfoDTO.isAuthorized()) {
                /*
                     * Set api.ut.apiPublisher of the subscribed api to the message context.
                     * This is necessary for the functionality of Publisher alerts.
                     * Set API_NAME of the subscribed api to the message context.
                     * */
                synCtx.setProperty(APIMgtGatewayConstants.API_PUBLISHER, apiKeyValidationInfoDTO.getApiPublisher());
                synCtx.setProperty("API_NAME", apiKeyValidationInfoDTO.getApiName());
                /* GraphQL Query Analysis Information */
                if (APIConstants.GRAPHQL_API.equals(synCtx.getProperty(APIConstants.API_TYPE))) {
                    synCtx.setProperty(APIConstants.MAXIMUM_QUERY_DEPTH, apiKeyValidationInfoDTO.getGraphQLMaxDepth());
                    synCtx.setProperty(APIConstants.MAXIMUM_QUERY_COMPLEXITY, apiKeyValidationInfoDTO.getGraphQLMaxComplexity());
                }
                log.debug("JWT authentication successful.");
            }
            log.debug("JWT authentication successful.");
            String endUserToken = null;
            if (jwtGenerationEnabled) {
                JWTInfoDto jwtInfoDto = GatewayUtils.generateJWTInfoDto(null, jwtValidationInfo, apiKeyValidationInfoDTO, synCtx);
                endUserToken = generateAndRetrieveJWTToken(jwtTokenIdentifier, jwtInfoDto);
            }
            return GatewayUtils.generateAuthenticationContext(jwtTokenIdentifier, jwtValidationInfo, apiKeyValidationInfoDTO, endUserToken, true);
        } else {
            throw new APISecurityException(jwtValidationInfo.getValidationCode(), APISecurityConstants.getAuthenticationFailureMessage(jwtValidationInfo.getValidationCode()));
        }
    } else {
        throw new APISecurityException(APISecurityConstants.API_AUTH_GENERAL_ERROR, APISecurityConstants.API_AUTH_GENERAL_ERROR_MESSAGE);
    }
}
Also used : APISecurityException(org.wso2.carbon.apimgt.gateway.handlers.security.APISecurityException) JWTInfoDto(org.wso2.carbon.apimgt.common.gateway.dto.JWTInfoDto) APIManagementException(org.wso2.carbon.apimgt.api.APIManagementException) X509Certificate(javax.security.cert.X509Certificate) APIKeyValidationInfoDTO(org.wso2.carbon.apimgt.impl.dto.APIKeyValidationInfoDTO) Axis2MessageContext(org.apache.synapse.core.axis2.Axis2MessageContext) JWTValidationInfo(org.wso2.carbon.apimgt.common.gateway.dto.JWTValidationInfo) MethodStats(org.wso2.carbon.apimgt.gateway.MethodStats)

Example 14 with SignedJWTInfo

use of org.wso2.carbon.apimgt.impl.jwt.SignedJWTInfo in project carbon-apimgt by wso2.

the class InboundWebsocketProcessorUtil method getSignedJwtInfo.

/**
 * Get signed JWT info for access token
 *
 * @param accessToken Access token
 * @return SignedJWTInfo
 * @throws ParseException if an error occurs
 */
private static SignedJWTInfo getSignedJwtInfo(String accessToken) throws ParseException {
    String signature = accessToken.split("\\.")[2];
    SignedJWTInfo signedJWTInfo = null;
    Cache gatewaySignedJWTParseCache = CacheProvider.getGatewaySignedJWTParseCache();
    if (gatewaySignedJWTParseCache != null) {
        Object cachedEntry = gatewaySignedJWTParseCache.get(signature);
        if (cachedEntry != null) {
            signedJWTInfo = (SignedJWTInfo) cachedEntry;
        }
        if (signedJWTInfo == null || !signedJWTInfo.getToken().equals(accessToken)) {
            SignedJWT signedJWT = SignedJWT.parse(accessToken);
            JWTClaimsSet jwtClaimsSet = signedJWT.getJWTClaimsSet();
            signedJWTInfo = new SignedJWTInfo(accessToken, signedJWT, jwtClaimsSet);
            gatewaySignedJWTParseCache.put(signature, signedJWTInfo);
        }
    } else {
        SignedJWT signedJWT = SignedJWT.parse(accessToken);
        JWTClaimsSet jwtClaimsSet = signedJWT.getJWTClaimsSet();
        signedJWTInfo = new SignedJWTInfo(accessToken, signedJWT, jwtClaimsSet);
    }
    return signedJWTInfo;
}
Also used : JWTClaimsSet(com.nimbusds.jwt.JWTClaimsSet) JSONObject(org.json.JSONObject) SignedJWT(com.nimbusds.jwt.SignedJWT) SignedJWTInfo(org.wso2.carbon.apimgt.impl.jwt.SignedJWTInfo) Cache(javax.cache.Cache)

Example 15 with SignedJWTInfo

use of org.wso2.carbon.apimgt.impl.jwt.SignedJWTInfo in project carbon-apimgt by wso2.

the class OAuthJwtAuthenticatorImpl method handleScopeValidation.

/**
 * Handle scope validation
 *
 * @param accessToken   JWT token
 * @param signedJWTInfo : Signed token info
 * @param message       : cxf Message
 */
private boolean handleScopeValidation(Message message, SignedJWTInfo signedJWTInfo, String accessToken) throws APIManagementException, ParseException {
    String maskedToken = message.get(RestApiConstants.MASKED_TOKEN).toString();
    OAuthTokenInfo oauthTokenInfo = new OAuthTokenInfo();
    oauthTokenInfo.setAccessToken(accessToken);
    oauthTokenInfo.setEndUserName(signedJWTInfo.getJwtClaimsSet().getSubject());
    String scopeClaim = signedJWTInfo.getJwtClaimsSet().getStringClaim(JwtTokenConstants.SCOPE);
    if (scopeClaim != null) {
        String orgId = RestApiUtil.resolveOrganization(message);
        String[] scopes = scopeClaim.split(JwtTokenConstants.SCOPE_DELIMITER);
        scopes = java.util.Arrays.stream(scopes).filter(s -> s.contains(orgId)).map(s -> s.replace(APIConstants.URN_CHOREO + orgId + ":", "")).toArray(size -> new String[size]);
        oauthTokenInfo.setScopes(scopes);
        if (validateScopes(message, oauthTokenInfo)) {
            // Add the user scopes list extracted from token to the cxf message
            message.getExchange().put(RestApiConstants.USER_REST_API_SCOPES, oauthTokenInfo.getScopes());
            // If scope validation successful then set tenant name and user name to current context
            String tenantDomain = MultitenantUtils.getTenantDomain(oauthTokenInfo.getEndUserName());
            int tenantId;
            PrivilegedCarbonContext carbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext();
            RealmService realmService = (RealmService) carbonContext.getOSGiService(RealmService.class, null);
            try {
                String username = oauthTokenInfo.getEndUserName();
                if (MultitenantConstants.SUPER_TENANT_DOMAIN_NAME.equals(tenantDomain)) {
                    // when the username is an email in supertenant, it has at least 2 occurrences of '@'
                    long count = username.chars().filter(ch -> ch == '@').count();
                    // in the case of email, there will be more than one '@'
                    boolean isEmailUsernameEnabled = Boolean.parseBoolean(CarbonUtils.getServerConfiguration().getFirstProperty("EnableEmailUserName"));
                    if (isEmailUsernameEnabled || (username.endsWith(SUPER_TENANT_SUFFIX) && count <= 1)) {
                        username = MultitenantUtils.getTenantAwareUsername(username);
                    }
                }
                if (log.isDebugEnabled()) {
                    log.debug("username = " + username + "masked token " + maskedToken);
                }
                tenantId = realmService.getTenantManager().getTenantId(tenantDomain);
                carbonContext.setTenantDomain(tenantDomain);
                carbonContext.setTenantId(tenantId);
                carbonContext.setUsername(username);
                message.put(RestApiConstants.SUB_ORGANIZATION, orgId);
                if (!tenantDomain.equals(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME)) {
                    APIUtil.loadTenantConfigBlockingMode(tenantDomain);
                }
                return true;
            } catch (UserStoreException e) {
                log.error("Error while retrieving tenant id for tenant domain: " + tenantDomain, e);
            }
            log.debug("Scope validation success for the token " + maskedToken);
            return true;
        }
        log.error("scopes validation failed for the token" + maskedToken);
        return false;
    }
    log.error("scopes validation failed for the token" + maskedToken);
    return false;
}
Also used : MultitenantConstants(org.wso2.carbon.utils.multitenancy.MultitenantConstants) UserStoreException(org.wso2.carbon.user.api.UserStoreException) URL(java.net.URL) Date(java.util.Date) JWTClaimsSet(com.nimbusds.jwt.JWTClaimsSet) AbstractOAuthAuthenticator(org.wso2.carbon.apimgt.rest.api.util.authenticators.AbstractOAuthAuthenticator) MethodStats(org.wso2.carbon.apimgt.rest.api.util.MethodStats) PrivilegedCarbonContext(org.wso2.carbon.context.PrivilegedCarbonContext) StringUtils(org.apache.commons.lang3.StringUtils) RealmService(org.wso2.carbon.user.core.service.RealmService) APIConstants(org.wso2.carbon.apimgt.impl.APIConstants) CarbonUtils(org.wso2.carbon.utils.CarbonUtils) RestApiConstants(org.wso2.carbon.apimgt.rest.api.common.RestApiConstants) SignedJWTInfo(org.wso2.carbon.apimgt.impl.jwt.SignedJWTInfo) Map(java.util.Map) ParseException(java.text.ParseException) RESTAPICacheConfiguration(org.wso2.carbon.apimgt.impl.RESTAPICacheConfiguration) DateUtils(com.nimbusds.jwt.util.DateUtils) MalformedURLException(java.net.MalformedURLException) Message(org.apache.cxf.message.Message) JwtTokenConstants(org.wso2.carbon.apimgt.impl.APIConstants.JwtTokenConstants) APIUtil(org.wso2.carbon.apimgt.impl.utils.APIUtil) APIMConfigUtil(org.wso2.carbon.apimgt.rest.api.common.APIMConfigUtil) TokenIssuerDto(org.wso2.carbon.apimgt.common.gateway.dto.TokenIssuerDto) RestApiUtil(org.wso2.carbon.apimgt.rest.api.util.utils.RestApiUtil) SignedJWT(com.nimbusds.jwt.SignedJWT) JWTValidationInfo(org.wso2.carbon.apimgt.common.gateway.dto.JWTValidationInfo) List(java.util.List) JWTValidator(org.wso2.carbon.apimgt.impl.jwt.JWTValidator) MultitenantUtils(org.wso2.carbon.utils.multitenancy.MultitenantUtils) APIManagementException(org.wso2.carbon.apimgt.api.APIManagementException) OAuthTokenInfo(org.wso2.carbon.apimgt.api.OAuthTokenInfo) Log(org.apache.commons.logging.Log) LogFactory(org.apache.commons.logging.LogFactory) APIMConfigUtil.getRestApiJWTAuthAudiences(org.wso2.carbon.apimgt.rest.api.common.APIMConfigUtil.getRestApiJWTAuthAudiences) RealmService(org.wso2.carbon.user.core.service.RealmService) UserStoreException(org.wso2.carbon.user.api.UserStoreException) OAuthTokenInfo(org.wso2.carbon.apimgt.api.OAuthTokenInfo) PrivilegedCarbonContext(org.wso2.carbon.context.PrivilegedCarbonContext)

Aggregations

JWTValidationInfo (org.wso2.carbon.apimgt.common.gateway.dto.JWTValidationInfo)22 SignedJWTInfo (org.wso2.carbon.apimgt.impl.jwt.SignedJWTInfo)18 SignedJWT (com.nimbusds.jwt.SignedJWT)15 APISecurityException (org.wso2.carbon.apimgt.gateway.handlers.security.APISecurityException)15 APIKeyValidationInfoDTO (org.wso2.carbon.apimgt.impl.dto.APIKeyValidationInfoDTO)15 Cache (javax.cache.Cache)12 Axis2MessageContext (org.apache.synapse.core.axis2.Axis2MessageContext)12 APIKeyValidator (org.wso2.carbon.apimgt.gateway.handlers.security.APIKeyValidator)11 AuthenticationContext (org.wso2.carbon.apimgt.gateway.handlers.security.AuthenticationContext)11 HashMap (java.util.HashMap)10 Test (org.junit.Test)10 PrepareForTest (org.powermock.core.classloader.annotations.PrepareForTest)10 ExtendedJWTConfigurationDto (org.wso2.carbon.apimgt.impl.dto.ExtendedJWTConfigurationDto)10 JWTValidationService (org.wso2.carbon.apimgt.impl.jwt.JWTValidationService)10 TokenValidationContext (org.wso2.carbon.apimgt.keymgt.service.TokenValidationContext)10 JWTClaimsSet (com.nimbusds.jwt.JWTClaimsSet)9 MessageContext (org.apache.synapse.MessageContext)9 APIManagerConfiguration (org.wso2.carbon.apimgt.impl.APIManagerConfiguration)9 APIManagementException (org.wso2.carbon.apimgt.api.APIManagementException)7 ParseException (java.text.ParseException)6