Search in sources :

Example 16 with Tokens

use of com.nimbusds.oauth2.sdk.token.Tokens 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 17 with Tokens

use of com.nimbusds.oauth2.sdk.token.Tokens in project ddf by codice.

the class OAuthPlugin method process.

/**
 * Verifies that a source configured to use OAuth has a valid access token to process and that the
 * user has authorized the use of their data against this source.
 *
 * @param source source being queried
 * @param input query request
 * @throws OAuthPluginException if the user's access token is not available or if the source is
 *     not authorized
 * @throws StopProcessingException for errors not related to OAuth
 */
@Override
public QueryRequest process(Source source, QueryRequest input) throws StopProcessingException {
    OAuthFederatedSource oauthSource = getSource(source);
    if (oauthSource == null) {
        return input;
    }
    Object securityAssertion = input.getProperties().get(SECURITY_SUBJECT);
    if (!(securityAssertion instanceof Subject)) {
        LOGGER.warn("The user's subject is not available.");
        throw new StopProcessingException("The user's subject is not available.");
    }
    Subject subject = (Subject) securityAssertion;
    Session session = subject.getSession(false);
    if (session == null) {
        LOGGER.warn("The user's session is not available.");
        throw new StopProcessingException("The user's session is not available.");
    }
    String sessionId = (String) session.getId();
    if (sessionId == null) {
        LOGGER.warn("The user's session ID is not available.");
        throw new StopProcessingException("The user's session ID is not available.");
    }
    OIDCProviderMetadata metadata;
    try {
        metadata = OIDCProviderMetadata.parse(resourceRetriever.retrieveResource(new URL(oauthSource.getOauthDiscoveryUrl())).getContent());
    } catch (OAuthServiceException | IOException | ParseException e) {
        LOGGER.error("Unable to retrieve OAuth provider's metadata for the {} source.", oauthSource.getId());
        throw new StopProcessingException("Unable to retrieve OAuth provider's metadata.");
    }
    TokenEntry tokenEntry = tokenStorage.read(sessionId, oauthSource.getId());
    if (tokenEntry == null) {
        // See if the user already logged in to the OAuth provider for a different source
        findExistingTokens(oauthSource, sessionId, metadata);
        throw createNoAuthException(oauthSource, sessionId, metadata, "the user's tokens were not found.");
    }
    // an outdated token)
    if (!oauthSource.getOauthDiscoveryUrl().equals(tokenEntry.getDiscoveryUrl())) {
        // the discoveryUrl is different from the one stored - the user must login
        tokenStorage.delete(sessionId, oauthSource.getId());
        findExistingTokens(oauthSource, sessionId, metadata);
        throw createNoAuthException(oauthSource, sessionId, metadata, "the oauth provider information has been changed and is different from the one stored.");
    }
    verifyAccessToken(oauthSource, sessionId, tokenEntry, metadata);
    return input;
}
Also used : OAuthFederatedSource(ddf.catalog.source.OAuthFederatedSource) OAuthServiceException(org.apache.cxf.rs.security.oauth2.provider.OAuthServiceException) StopProcessingException(ddf.catalog.plugin.StopProcessingException) IOException(java.io.IOException) Subject(ddf.security.Subject) URL(java.net.URL) DISCOVERY_URL(org.codice.ddf.security.token.storage.api.TokenStorage.DISCOVERY_URL) TokenEntry(org.codice.ddf.security.token.storage.api.TokenInformation.TokenEntry) OIDCProviderMetadata(com.nimbusds.openid.connect.sdk.op.OIDCProviderMetadata) ParseException(com.nimbusds.oauth2.sdk.ParseException) Session(org.apache.shiro.session.Session)

Example 18 with Tokens

use of com.nimbusds.oauth2.sdk.token.Tokens in project syncope by apache.

the class OIDCC4UILogic method login.

@PreAuthorize("hasRole('" + IdRepoEntitlement.ANONYMOUS + "')")
public OIDCLoginResponse login(final String redirectURI, final String authorizationCode, final String opName) {
    // 0. look for OP
    OIDCC4UIProvider op = opDAO.findByName(opName);
    if (op == null) {
        throw new NotFoundException("OIDC Provider '" + opName + '\'');
    }
    // 1. look for configured client
    OidcClient oidcClient = getOidcClient(opName, redirectURI);
    oidcClient.setCallbackUrl(redirectURI);
    // 2. get OpenID Connect tokens
    String idTokenHint;
    JWTClaimsSet idToken;
    try {
        OidcCredentials credentials = new OidcCredentials();
        credentials.setCode(new AuthorizationCode(authorizationCode));
        OIDC4UIContext ctx = new OIDC4UIContext();
        oidcClient.getAuthenticator().validate(credentials, ctx, NoOpSessionStore.INSTANCE);
        idToken = credentials.getIdToken().getJWTClaimsSet();
        idTokenHint = credentials.getIdToken().serialize();
    } catch (Exception e) {
        LOG.error("While validating Token Response", e);
        SyncopeClientException sce = SyncopeClientException.build(ClientExceptionType.Unknown);
        sce.getElements().add(e.getMessage());
        throw sce;
    }
    // 3. prepare the result
    OIDCLoginResponse loginResponse = new OIDCLoginResponse();
    loginResponse.setLogoutSupported(StringUtils.isNotBlank(op.getEndSessionEndpoint()));
    // 3a. find matching user (if any) and return the received attributes
    String keyValue = idToken.getSubject();
    for (OIDCC4UIProviderItem item : op.getItems()) {
        Attr attrTO = new Attr();
        attrTO.setSchema(item.getExtAttrName());
        String value = idToken.getClaim(item.getExtAttrName()) == null ? null : idToken.getClaim(item.getExtAttrName()).toString();
        if (value != null) {
            attrTO.getValues().add(value);
            loginResponse.getAttrs().add(attrTO);
            if (item.isConnObjectKey()) {
                keyValue = value;
            }
        }
    }
    List<String> matchingUsers = keyValue == null ? List.of() : userManager.findMatchingUser(keyValue, op.getConnObjectKeyItem().get());
    LOG.debug("Found {} matching users for {}", matchingUsers.size(), keyValue);
    // 3b. not found: create or selfreg if configured
    String username;
    if (matchingUsers.isEmpty()) {
        if (op.isCreateUnmatching()) {
            LOG.debug("No user matching {}, about to create", keyValue);
            String defaultUsername = keyValue;
            username = AuthContextUtils.callAsAdmin(AuthContextUtils.getDomain(), () -> userManager.create(op, loginResponse, defaultUsername));
        } else if (op.isSelfRegUnmatching()) {
            UserTO userTO = new UserTO();
            userManager.fill(op, loginResponse, userTO);
            loginResponse.getAttrs().clear();
            loginResponse.getAttrs().addAll(userTO.getPlainAttrs());
            if (StringUtils.isNotBlank(userTO.getUsername())) {
                loginResponse.setUsername(userTO.getUsername());
            } else {
                loginResponse.setUsername(keyValue);
            }
            loginResponse.setSelfReg(true);
            return loginResponse;
        } else {
            throw new NotFoundException(Optional.ofNullable(keyValue).map(value -> "User matching the provided value " + value).orElse("User marching the provided claims"));
        }
    } else if (matchingUsers.size() > 1) {
        throw new IllegalArgumentException("Several users match the provided value " + keyValue);
    } else {
        if (op.isUpdateMatching()) {
            LOG.debug("About to update {} for {}", matchingUsers.get(0), keyValue);
            username = AuthContextUtils.callAsAdmin(AuthContextUtils.getDomain(), () -> userManager.update(matchingUsers.get(0), op, loginResponse));
        } else {
            username = matchingUsers.get(0);
        }
    }
    loginResponse.setUsername(username);
    // 4. generate JWT for further access
    Map<String, Object> claims = new HashMap<>();
    claims.put(JWT_CLAIM_OP_NAME, opName);
    claims.put(JWT_CLAIM_ID_TOKEN, idTokenHint);
    byte[] authorities = null;
    try {
        authorities = ENCRYPTOR.encode(POJOHelper.serialize(authDataAccessor.getAuthorities(loginResponse.getUsername(), null)), CipherAlgorithm.AES).getBytes();
    } catch (Exception e) {
        LOG.error("Could not fetch authorities", e);
    }
    Pair<String, OffsetDateTime> accessTokenInfo = accessTokenDataBinder.create(loginResponse.getUsername(), claims, authorities, true);
    loginResponse.setAccessToken(accessTokenInfo.getLeft());
    loginResponse.setAccessTokenExpiryTime(accessTokenInfo.getRight());
    return loginResponse;
}
Also used : OIDCC4UIProvider(org.apache.syncope.core.persistence.api.entity.OIDCC4UIProvider) Attr(org.apache.syncope.common.lib.Attr) NoOpSessionStore(org.apache.syncope.core.logic.oidc.NoOpSessionStore) POJOHelper(org.apache.syncope.core.provisioning.api.serialization.POJOHelper) OidcCredentials(org.pac4j.oidc.credentials.OidcCredentials) SyncopeClientException(org.apache.syncope.common.lib.SyncopeClientException) OIDC4UIContext(org.apache.syncope.core.logic.oidc.OIDC4UIContext) PreAuthorize(org.springframework.security.access.prepost.PreAuthorize) JWTClaimsSet(com.nimbusds.jwt.JWTClaimsSet) HashMap(java.util.HashMap) StringUtils(org.apache.commons.lang3.StringUtils) OIDCLoginResponse(org.apache.syncope.common.lib.oidc.OIDCLoginResponse) EntityTO(org.apache.syncope.common.lib.to.EntityTO) Pair(org.apache.commons.lang3.tuple.Pair) OidcClient(org.pac4j.oidc.client.OidcClient) OIDCC4UIProviderItem(org.apache.syncope.core.persistence.api.entity.OIDCC4UIProviderItem) Map(java.util.Map) ClientExceptionType(org.apache.syncope.common.lib.types.ClientExceptionType) AuthContextUtils(org.apache.syncope.core.spring.security.AuthContextUtils) ParseException(java.text.ParseException) OIDCClientCache(org.apache.syncope.core.logic.oidc.OIDCClientCache) Method(java.lang.reflect.Method) CipherAlgorithm(org.apache.syncope.common.lib.types.CipherAlgorithm) OidcProfile(org.pac4j.oidc.profile.OidcProfile) Encryptor(org.apache.syncope.core.spring.security.Encryptor) AccessTokenDataBinder(org.apache.syncope.core.provisioning.api.data.AccessTokenDataBinder) WithLocationAction(org.pac4j.core.exception.http.WithLocationAction) AuthDataAccessor(org.apache.syncope.core.spring.security.AuthDataAccessor) SignedJWT(com.nimbusds.jwt.SignedJWT) IdRepoEntitlement(org.apache.syncope.common.lib.types.IdRepoEntitlement) NotFoundException(org.apache.syncope.core.persistence.api.dao.NotFoundException) OIDCUserManager(org.apache.syncope.core.logic.oidc.OIDCUserManager) List(java.util.List) OffsetDateTime(java.time.OffsetDateTime) AuthorizationCode(com.nimbusds.oauth2.sdk.AuthorizationCode) OIDCC4UIProviderDAO(org.apache.syncope.core.persistence.api.dao.OIDCC4UIProviderDAO) Optional(java.util.Optional) OIDCRequest(org.apache.syncope.common.lib.oidc.OIDCRequest) UserTO(org.apache.syncope.common.lib.to.UserTO) AuthorizationCode(com.nimbusds.oauth2.sdk.AuthorizationCode) OIDC4UIContext(org.apache.syncope.core.logic.oidc.OIDC4UIContext) OIDCC4UIProviderItem(org.apache.syncope.core.persistence.api.entity.OIDCC4UIProviderItem) HashMap(java.util.HashMap) SyncopeClientException(org.apache.syncope.common.lib.SyncopeClientException) NotFoundException(org.apache.syncope.core.persistence.api.dao.NotFoundException) SyncopeClientException(org.apache.syncope.common.lib.SyncopeClientException) ParseException(java.text.ParseException) NotFoundException(org.apache.syncope.core.persistence.api.dao.NotFoundException) Attr(org.apache.syncope.common.lib.Attr) OIDCC4UIProvider(org.apache.syncope.core.persistence.api.entity.OIDCC4UIProvider) OIDCLoginResponse(org.apache.syncope.common.lib.oidc.OIDCLoginResponse) OidcCredentials(org.pac4j.oidc.credentials.OidcCredentials) OidcClient(org.pac4j.oidc.client.OidcClient) OffsetDateTime(java.time.OffsetDateTime) JWTClaimsSet(com.nimbusds.jwt.JWTClaimsSet) UserTO(org.apache.syncope.common.lib.to.UserTO) PreAuthorize(org.springframework.security.access.prepost.PreAuthorize)

Example 19 with Tokens

use of com.nimbusds.oauth2.sdk.token.Tokens in project kf-key-management by kids-first.

the class FenceService method refreshTokens.

public Mono<OIDCTokens> refreshTokens(String refreshToken, AllFences.Fence fence) {
    Mono<Optional<OIDCTokens>> blockingWrapper = Mono.fromCallable(() -> {
        val clientId = fence.getClientId();
        val clientSecret = fence.getClientSecret();
        val fenceEndpoint = fence.getTokenEndpoint();
        val request = new TokenRequest(new URI(fenceEndpoint), new ClientSecretBasic(new ClientID(clientId), new com.nimbusds.oauth2.sdk.auth.Secret(clientSecret)), new RefreshTokenGrant(new RefreshToken(refreshToken)));
        val fenceResponse = request.toHTTPRequest().send();
        if (fenceResponse.indicatesSuccess()) {
            val tokens = OIDCTokenResponse.parse(fenceResponse).toSuccessResponse().getOIDCTokens();
            return Optional.of(tokens);
        }
        return Optional.empty();
    });
    return blockingWrapper.subscribeOn(Schedulers.boundedElastic()).flatMap(o -> o.map(Mono::just).orElseGet(Mono::empty));
}
Also used : lombok.val(lombok.val) Optional(java.util.Optional) Mono(reactor.core.publisher.Mono) URI(java.net.URI) ClientSecretBasic(com.nimbusds.oauth2.sdk.auth.ClientSecretBasic) RefreshToken(com.nimbusds.oauth2.sdk.token.RefreshToken) ClientID(com.nimbusds.oauth2.sdk.id.ClientID) com.nimbusds.oauth2.sdk(com.nimbusds.oauth2.sdk)

Example 20 with Tokens

use of com.nimbusds.oauth2.sdk.token.Tokens in project kf-key-management by kids-first.

the class FenceService method requestTokens.

public Mono<OIDCTokens> requestTokens(String authCode, AllFences.Fence fence) {
    Mono<Optional<OIDCTokens>> blockingWrapper = Mono.fromCallable(() -> {
        String clientId = fence.getClientId();
        String clientSecret = fence.getClientSecret();
        String fenceEndpoint = fence.getTokenEndpoint();
        String redirectUri = fence.getRedirectUri();
        val fenceRequest = new TokenRequest(new URI(fenceEndpoint), new ClientSecretBasic(new ClientID(clientId), new com.nimbusds.oauth2.sdk.auth.Secret(clientSecret)), new AuthorizationCodeGrant(new AuthorizationCode(authCode), new URI(redirectUri)), new Scope(fence.getScope()));
        val fenceResponse = fenceRequest.toHTTPRequest().send();
        if (fenceResponse.indicatesSuccess()) {
            val tokens = OIDCTokenResponse.parse(fenceResponse).toSuccessResponse().getOIDCTokens();
            return Optional.of(tokens);
        } else {
            log.error("Error in  {} fence response during request tokens: status={}, content={}", fence.getName(), fenceResponse.getStatusCode(), fenceResponse.getContent());
            return Optional.empty();
        }
    });
    return blockingWrapper.subscribeOn(Schedulers.boundedElastic()).flatMap(o -> o.map(Mono::just).orElseGet(Mono::empty));
}
Also used : lombok.val(lombok.val) Optional(java.util.Optional) Mono(reactor.core.publisher.Mono) URI(java.net.URI) ClientSecretBasic(com.nimbusds.oauth2.sdk.auth.ClientSecretBasic) ClientID(com.nimbusds.oauth2.sdk.id.ClientID) com.nimbusds.oauth2.sdk(com.nimbusds.oauth2.sdk)

Aggregations

URI (java.net.URI)18 OIDCTokens (com.nimbusds.openid.connect.sdk.token.OIDCTokens)17 ClientSecretBasic (com.nimbusds.oauth2.sdk.auth.ClientSecretBasic)15 ClientID (com.nimbusds.oauth2.sdk.id.ClientID)15 OIDCTokenResponse (com.nimbusds.openid.connect.sdk.OIDCTokenResponse)15 TokenResponse (com.nimbusds.oauth2.sdk.TokenResponse)14 TokenRequest (com.nimbusds.oauth2.sdk.TokenRequest)13 BearerAccessToken (com.nimbusds.oauth2.sdk.token.BearerAccessToken)13 Secret (com.nimbusds.oauth2.sdk.auth.Secret)12 HTTPResponse (com.nimbusds.oauth2.sdk.http.HTTPResponse)12 Tokens (com.nimbusds.oauth2.sdk.token.Tokens)11 TokenErrorResponse (com.nimbusds.oauth2.sdk.TokenErrorResponse)10 ClientAuthentication (com.nimbusds.oauth2.sdk.auth.ClientAuthentication)10 AccessToken (com.nimbusds.oauth2.sdk.token.AccessToken)10 IOException (java.io.IOException)10 AccessTokenResponse (com.nimbusds.oauth2.sdk.AccessTokenResponse)8 Scope (com.nimbusds.oauth2.sdk.Scope)8 RefreshToken (com.nimbusds.oauth2.sdk.token.RefreshToken)8 HashMap (java.util.HashMap)8 Test (org.testng.annotations.Test)8