Search in sources :

Example 1 with OidcValidationException

use of org.codice.ddf.security.oidc.validator.OidcValidationException in project ddf by codice.

the class OAuthPlugin method refreshTokens.

/**
 * Attempts to refresh the user's access token and saves the new tokens in the token storage
 *
 * @param refreshToken refresh token used to refresh access token
 * @param oauthSource source being queried
 * @throws OAuthPluginException if the access token could not be renewed
 */
private void refreshTokens(String refreshToken, OAuthFederatedSource oauthSource, String sessionId, OIDCProviderMetadata metadata) throws StopProcessingException {
    if (refreshToken == null) {
        throw createNoAuthException(oauthSource, sessionId, metadata, "unable to find the user's refresh token.");
    }
    ClientAccessToken clientAccessToken;
    try {
        LOGGER.debug("Attempting to refresh the user's access token.");
        WebClient webClient = createWebclient(metadata.getTokenEndpointURI().toURL().toString());
        Consumer consumer = new Consumer(oauthSource.getOauthClientId(), oauthSource.getOauthClientSecret());
        AccessTokenGrant accessTokenGrant = new RefreshTokenGrant(refreshToken);
        clientAccessToken = OAuthClientUtils.getAccessToken(webClient, consumer, accessTokenGrant);
    } catch (OAuthServiceException e) {
        String error = e.getError() != null ? e.getError().getError() : "";
        throw createNoAuthException(oauthSource, sessionId, metadata, "failed to refresh access token " + error);
    } catch (MalformedURLException e) {
        throw createNoAuthException(oauthSource, sessionId, metadata, "malformed token endpoint URL. " + e.getMessage());
    }
    // Validate new access token
    try {
        AccessToken accessToken = convertCxfAccessTokenToNimbusdsToken(clientAccessToken);
        OidcTokenValidator.validateAccessToken(accessToken, null, resourceRetriever, metadata, null);
    } catch (OidcValidationException e) {
        throw createNoAuthException(oauthSource, sessionId, metadata, "failed to validate refreshed access token.");
    }
    // Store new tokens
    String newAccessToken = clientAccessToken.getTokenKey();
    String newRefreshToken = clientAccessToken.getRefreshToken();
    int status = tokenStorage.create(sessionId, oauthSource.getId(), newAccessToken, newRefreshToken, oauthSource.getOauthDiscoveryUrl());
    if (status != SC_OK) {
        LOGGER.warn("Error updating the token information.");
    }
}
Also used : MalformedURLException(java.net.MalformedURLException) Consumer(org.apache.cxf.rs.security.oauth2.client.Consumer) OAuthServiceException(org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException) RefreshTokenGrant(org.apache.cxf.rs.security.oauth2.grants.refresh.RefreshTokenGrant) ClientAccessToken(org.apache.cxf.rs.security.oauth2.common.ClientAccessToken) AccessToken(com.nimbusds.oauth2.sdk.token.AccessToken) BearerAccessToken(com.nimbusds.oauth2.sdk.token.BearerAccessToken) TypelessAccessToken(com.nimbusds.oauth2.sdk.token.TypelessAccessToken) ClientAccessToken(org.apache.cxf.rs.security.oauth2.common.ClientAccessToken) AccessTokenGrant(org.apache.cxf.rs.security.oauth2.common.AccessTokenGrant) WebClient(org.apache.cxf.jaxrs.client.WebClient) OidcValidationException(org.codice.ddf.security.oidc.validator.OidcValidationException)

Example 2 with OidcValidationException

use of org.codice.ddf.security.oidc.validator.OidcValidationException in project ddf by codice.

the class OidcCredentialsResolver method trySendingGrantAndPopulatingCredentials.

private void trySendingGrantAndPopulatingCredentials(AuthorizationGrant grant, OidcCredentials credentials, WebContext webContext) throws IOException, ParseException {
    final OIDCTokens oidcTokens = getOidcTokens(grant);
    try {
        JWT idToken = oidcTokens.getIDToken();
        if (idToken != null) {
            OidcTokenValidator.validateIdTokens(idToken, webContext, configuration, client);
        }
        AccessToken accessToken = oidcTokens.getAccessToken();
        if (accessToken != null) {
            OidcTokenValidator.validateAccessToken(accessToken, idToken, resourceRetriever, metadata, configuration);
        }
        credentials.setAccessToken(accessToken);
        credentials.setIdToken(idToken);
        credentials.setRefreshToken(oidcTokens.getRefreshToken());
    } catch (OidcValidationException e) {
        throw new TechnicalException(e);
    }
}
Also used : TechnicalException(org.pac4j.core.exception.TechnicalException) PlainJWT(com.nimbusds.jwt.PlainJWT) JWT(com.nimbusds.jwt.JWT) AccessToken(com.nimbusds.oauth2.sdk.token.AccessToken) BearerAccessToken(com.nimbusds.oauth2.sdk.token.BearerAccessToken) OIDCTokens(com.nimbusds.openid.connect.sdk.token.OIDCTokens) OidcValidationException(org.codice.ddf.security.oidc.validator.OidcValidationException)

Example 3 with OidcValidationException

use of org.codice.ddf.security.oidc.validator.OidcValidationException in project ddf by codice.

the class OAuthSecurityImpl method getNewAccessToken.

/**
 * Gets an access token from the configured OAuth provider, saves it to the token storage and
 * returns it
 *
 * @param id The ID to use when storing tokens
 * @param sourceId The ID of the source using OAuth to use when storing tokens
 * @param encodedClientIdSecret The base 64 encoded clientId:secret
 * @param discoveryUrl The URL where the Oauth provider's metadata is hosted
 * @param grantType The OAuth grand type to use
 * @param queryParameters Query parameters to send
 * @return a client access token or null if one could not be returned
 */
private String getNewAccessToken(String id, String sourceId, String encodedClientIdSecret, String discoveryUrl, String grantType, Map<String, String> queryParameters, OIDCProviderMetadata metadata) {
    WebClient webClient = createWebClient(metadata.getTokenEndpointURI());
    webClient.header(AUTHORIZATION, BASIC + encodedClientIdSecret);
    webClient.accept(APPLICATION_JSON);
    Form formParam = new Form(GRANT_TYPE, grantType);
    formParam.param(SCOPE, OPENID_SCOPE);
    queryParameters.forEach(formParam::param);
    javax.ws.rs.core.Response response = webClient.form(formParam);
    String body;
    try {
        body = IOUtils.toString((InputStream) response.getEntity(), UTF_8);
    } catch (IOException e) {
        LOGGER.debug("Unable to retrieve system access token.", e);
        return null;
    }
    if (response.getStatus() != HttpStatus.SC_OK) {
        LOGGER.debug("Unable to retrieve system access token. {}", body);
        if (LOGGER.isTraceEnabled()) {
            sanitizeFormParameters(formParam);
            LOGGER.trace("Unable to retrieve system access token. Headers: {}, Request: {}, Status: {}, Response: {}", webClient.getHeaders(), formParam.asMap(), response.getStatus(), body);
        }
        return null;
    }
    Map<String, String> map = GSON.fromJson(body, MAP_STRING_TO_OBJECT_TYPE);
    String idToken = map.get(ID_TOKEN);
    String accessToken = map.get(ACCESS_TOKEN);
    String refreshToken = map.get(REFRESH_TOKEN);
    JWT jwt = null;
    try {
        if (idToken != null) {
            jwt = SignedJWT.parse(idToken);
        }
    } catch (java.text.ParseException e) {
        LOGGER.debug("Error parsing ID token.", e);
    }
    try {
        OidcTokenValidator.validateAccessToken(new BearerAccessToken(accessToken), jwt, resourceRetriever, metadata, null);
    } catch (OidcValidationException e) {
        LOGGER.warn("Error validating system access token.", e);
        return null;
    }
    LOGGER.debug("Successfully retrieved system access token.");
    int status = tokenStorage.create(id, sourceId, accessToken, refreshToken, discoveryUrl);
    if (status != SC_OK) {
        LOGGER.debug("Error storing user token.");
    }
    return accessToken;
}
Also used : Form(javax.ws.rs.core.Form) InputStream(java.io.InputStream) JWT(com.nimbusds.jwt.JWT) SignedJWT(com.nimbusds.jwt.SignedJWT) IOException(java.io.IOException) WebClient(org.apache.cxf.jaxrs.client.WebClient) OidcValidationException(org.codice.ddf.security.oidc.validator.OidcValidationException) BearerAccessToken(com.nimbusds.oauth2.sdk.token.BearerAccessToken)

Example 4 with OidcValidationException

use of org.codice.ddf.security.oidc.validator.OidcValidationException in project ddf by codice.

the class OAuthSecurityImpl method refreshToken.

/**
 * Attempts to refresh an expired access token
 *
 * @param id The ID to use when storing tokens
 * @param sourceId The ID of the source using OAuth to use when storing tokens
 * @param clientId The client ID registered with the OAuth provider
 * @param clientSecret The client secret registered with the OAuth provider
 * @param discoveryUrl The URL where the OAuth provider's metadata is hosted
 * @param refreshToken The unexpired refresh token to use
 * @param metadata The OAuh provider's metadata
 * @return refreshed access token
 */
private String refreshToken(String id, String sourceId, String clientId, String clientSecret, String discoveryUrl, String refreshToken, OIDCProviderMetadata metadata) {
    if (refreshToken == null || isExpired(refreshToken)) {
        LOGGER.debug("Error refreshing access token: unable to find an unexpired refresh token.");
        return null;
    }
    ClientAccessToken clientAccessToken;
    try {
        LOGGER.debug("Attempting to refresh the user's access token.");
        WebClient webClient = createWebClient(metadata.getTokenEndpointURI());
        Consumer consumer = new Consumer(clientId, clientSecret);
        AccessTokenGrant accessTokenGrant = new RefreshTokenGrant(refreshToken);
        clientAccessToken = OAuthClientUtils.getAccessToken(webClient, consumer, accessTokenGrant);
    } catch (OAuthServiceException e) {
        LOGGER.debug("Error refreshing access token.", e);
        return null;
    }
    // Validate new access token
    try {
        AccessToken accessToken = convertCxfAccessTokenToNimbusdsToken(clientAccessToken);
        OidcTokenValidator.validateAccessToken(accessToken, null, resourceRetriever, metadata, null);
    } catch (OidcValidationException e) {
        LOGGER.debug("Error validating access token.");
        return null;
    }
    // Store new tokens
    String newAccessToken = clientAccessToken.getTokenKey();
    String newRefreshToken = clientAccessToken.getRefreshToken();
    int status = tokenStorage.create(id, sourceId, newAccessToken, newRefreshToken, discoveryUrl);
    if (status != SC_OK) {
        LOGGER.warn("Error updating the token information.");
    }
    return newAccessToken;
}
Also used : Consumer(org.apache.cxf.rs.security.oauth2.client.Consumer) OAuthServiceException(org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException) RefreshTokenGrant(org.apache.cxf.rs.security.oauth2.grants.refresh.RefreshTokenGrant) ClientAccessToken(org.apache.cxf.rs.security.oauth2.common.ClientAccessToken) AccessToken(com.nimbusds.oauth2.sdk.token.AccessToken) BearerAccessToken(com.nimbusds.oauth2.sdk.token.BearerAccessToken) TypelessAccessToken(com.nimbusds.oauth2.sdk.token.TypelessAccessToken) ClientAccessToken(org.apache.cxf.rs.security.oauth2.common.ClientAccessToken) AccessTokenGrant(org.apache.cxf.rs.security.oauth2.common.AccessTokenGrant) WebClient(org.apache.cxf.jaxrs.client.WebClient) OidcValidationException(org.codice.ddf.security.oidc.validator.OidcValidationException)

Example 5 with OidcValidationException

use of org.codice.ddf.security.oidc.validator.OidcValidationException in project ddf by codice.

the class OidcCredentialsResolver method resolveIdToken.

/* This methods job is to try and get an id token from a
  1. refresh token
  2. authorization code
  3. access token
  */
public void resolveIdToken(OidcCredentials credentials, WebContext webContext) {
    final AccessToken initialAccessToken = credentials.getAccessToken();
    final JWT initialIdToken = credentials.getIdToken();
    try {
        OidcTokenValidator.validateAccessToken(initialAccessToken, initialIdToken, resourceRetriever, metadata, configuration);
        if (initialIdToken != null) {
            OidcTokenValidator.validateIdTokens(initialIdToken, webContext, configuration, client);
            return;
        }
    } catch (OidcValidationException e) {
        throw new TechnicalException(e);
    }
    final RefreshToken initialRefreshToken = credentials.getRefreshToken();
    final AuthorizationCode initialAuthorizationCode = credentials.getCode();
    final List<AuthorizationGrant> grantList = new ArrayList<>();
    if (initialRefreshToken != null) {
        grantList.add(new RefreshTokenGrant(initialRefreshToken));
    }
    if (initialAuthorizationCode != null) {
        try {
            final URI callbackUri = new URI(client.computeFinalCallbackUrl(webContext));
            grantList.add(new AuthorizationCodeGrant(initialAuthorizationCode, callbackUri));
        } catch (URISyntaxException e) {
            LOGGER.debug("Problem computing callback url. Cannot add authorization code grant.");
        }
    }
    // try to get id token using refresh token and authorization code
    for (AuthorizationGrant grant : grantList) {
        try {
            trySendingGrantAndPopulatingCredentials(grant, credentials, webContext);
            if (credentials.getIdToken() != null) {
                break;
            }
        } catch (IOException | ParseException e) {
            LOGGER.debug("Problem sending grant ({}).", grant, e);
        }
    }
    // try to get id token using access token
    if (credentials.getIdToken() == null && initialAccessToken != null) {
        final UserInfoRequest userInfoRequest = new UserInfoRequest(metadata.getUserInfoEndpointURI(), Method.GET, new BearerAccessToken(initialAccessToken.toString()));
        final HTTPRequest userInfoHttpRequest = userInfoRequest.toHTTPRequest();
        try {
            final HTTPResponse httpResponse = userInfoHttpRequest.send();
            final UserInfoResponse userInfoResponse = UserInfoResponse.parse(httpResponse);
            if (userInfoResponse instanceof UserInfoSuccessResponse) {
                final UserInfoSuccessResponse userInfoSuccessResponse = (UserInfoSuccessResponse) userInfoResponse;
                JWT idToken = userInfoSuccessResponse.getUserInfoJWT();
                if (idToken == null && userInfoSuccessResponse.getUserInfo().toJWTClaimsSet() != null) {
                    idToken = new PlainJWT(userInfoSuccessResponse.getUserInfo().toJWTClaimsSet());
                }
                OidcTokenValidator.validateUserInfoIdToken(idToken, resourceRetriever, metadata);
                credentials.setIdToken(idToken);
            } else {
                throw new TechnicalException("Received a non-successful UserInfoResponse.");
            }
        } catch (IOException | ParseException | OidcValidationException e) {
            LOGGER.debug("Problem retrieving id token using access token.", e);
            throw new TechnicalException(e);
        }
    }
}
Also used : AuthorizationCode(com.nimbusds.oauth2.sdk.AuthorizationCode) HTTPRequest(com.nimbusds.oauth2.sdk.http.HTTPRequest) PlainJWT(com.nimbusds.jwt.PlainJWT) TechnicalException(org.pac4j.core.exception.TechnicalException) UserInfoSuccessResponse(com.nimbusds.openid.connect.sdk.UserInfoSuccessResponse) PlainJWT(com.nimbusds.jwt.PlainJWT) JWT(com.nimbusds.jwt.JWT) RefreshTokenGrant(com.nimbusds.oauth2.sdk.RefreshTokenGrant) HTTPResponse(com.nimbusds.oauth2.sdk.http.HTTPResponse) ArrayList(java.util.ArrayList) UserInfoRequest(com.nimbusds.openid.connect.sdk.UserInfoRequest) URISyntaxException(java.net.URISyntaxException) IOException(java.io.IOException) URI(java.net.URI) OidcValidationException(org.codice.ddf.security.oidc.validator.OidcValidationException) RefreshToken(com.nimbusds.oauth2.sdk.token.RefreshToken) AuthorizationCodeGrant(com.nimbusds.oauth2.sdk.AuthorizationCodeGrant) AccessToken(com.nimbusds.oauth2.sdk.token.AccessToken) BearerAccessToken(com.nimbusds.oauth2.sdk.token.BearerAccessToken) ParseException(com.nimbusds.oauth2.sdk.ParseException) BearerAccessToken(com.nimbusds.oauth2.sdk.token.BearerAccessToken) UserInfoResponse(com.nimbusds.openid.connect.sdk.UserInfoResponse) AuthorizationGrant(com.nimbusds.oauth2.sdk.AuthorizationGrant)

Aggregations

BearerAccessToken (com.nimbusds.oauth2.sdk.token.BearerAccessToken)5 OidcValidationException (org.codice.ddf.security.oidc.validator.OidcValidationException)5 AccessToken (com.nimbusds.oauth2.sdk.token.AccessToken)4 JWT (com.nimbusds.jwt.JWT)3 WebClient (org.apache.cxf.jaxrs.client.WebClient)3 PlainJWT (com.nimbusds.jwt.PlainJWT)2 TypelessAccessToken (com.nimbusds.oauth2.sdk.token.TypelessAccessToken)2 IOException (java.io.IOException)2 Consumer (org.apache.cxf.rs.security.oauth2.client.Consumer)2 AccessTokenGrant (org.apache.cxf.rs.security.oauth2.common.AccessTokenGrant)2 ClientAccessToken (org.apache.cxf.rs.security.oauth2.common.ClientAccessToken)2 RefreshTokenGrant (org.apache.cxf.rs.security.oauth2.grants.refresh.RefreshTokenGrant)2 OAuthServiceException (org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException)2 TechnicalException (org.pac4j.core.exception.TechnicalException)2 SignedJWT (com.nimbusds.jwt.SignedJWT)1 AuthorizationCode (com.nimbusds.oauth2.sdk.AuthorizationCode)1 AuthorizationCodeGrant (com.nimbusds.oauth2.sdk.AuthorizationCodeGrant)1 AuthorizationGrant (com.nimbusds.oauth2.sdk.AuthorizationGrant)1 ParseException (com.nimbusds.oauth2.sdk.ParseException)1 RefreshTokenGrant (com.nimbusds.oauth2.sdk.RefreshTokenGrant)1