Search in sources :

Example 1 with RefreshToken

use of oidc.model.RefreshToken in project OpenConext-oidcng by OpenConext.

the class TokenController method convertToken.

private Map<String, Object> convertToken(AccessToken token) {
    Map<String, Object> result = new HashMap<>();
    result.put("id", token.getId());
    Optional<OpenIDClient> optionalClient = openIDClientRepository.findOptionalByClientId(token.getClientId());
    if (!optionalClient.isPresent()) {
        return result;
    }
    OpenIDClient openIDClient = optionalClient.get();
    result.put("clientId", openIDClient.getClientId());
    result.put("clientName", openIDClient.getName());
    List<OpenIDClient> resourceServers = openIDClient.getAllowedResourceServers().stream().map(rs -> openIDClientRepository.findOptionalByClientId(rs)).filter(Optional::isPresent).map(Optional::get).collect(toList());
    result.put("audiences", resourceServers.stream().map(OpenIDClient::getName));
    result.put("createdAt", token.getCreatedAt());
    result.put("expiresIn", token.getExpiresIn());
    result.put("type", token instanceof RefreshToken ? TokenType.REFRESH : TokenType.ACCESS);
    Map<String, Scope> allScopes = resourceServers.stream().map(OpenIDClient::getScopes).flatMap(List::stream).filter(distinctByKey(Scope::getName)).collect(toMap(Scope::getName, s -> s));
    List<Scope> scopes = token.getScopes().stream().filter(name -> !name.equalsIgnoreCase("openid")).map(allScopes::get).filter(Objects::nonNull).collect(toList());
    result.put("scopes", scopes);
    return result;
}
Also used : TokenType(oidc.model.TokenType) RequestParam(org.springframework.web.bind.annotation.RequestParam) java.util(java.util) URLDecoder(java.net.URLDecoder) PreAuthorize(org.springframework.security.access.prepost.PreAuthorize) RefreshTokenRepository(oidc.repository.RefreshTokenRepository) Function(java.util.function.Function) Value(org.springframework.beans.factory.annotation.Value) RequestBody(org.springframework.web.bind.annotation.RequestBody) KeyGenerator(oidc.crypto.KeyGenerator) PutMapping(org.springframework.web.bind.annotation.PutMapping) Charset(java.nio.charset.Charset) Collectors.toMap(java.util.stream.Collectors.toMap) GetMapping(org.springframework.web.bind.annotation.GetMapping) OpenIDClient(oidc.model.OpenIDClient) TokenRepresentation(oidc.model.TokenRepresentation) Predicate(java.util.function.Predicate) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) AccessTokenRepository(oidc.repository.AccessTokenRepository) RestController(org.springframework.web.bind.annotation.RestController) Collectors(java.util.stream.Collectors) HttpStatus(org.springframework.http.HttpStatus) AccessToken(oidc.model.AccessToken) Collectors.toList(java.util.stream.Collectors.toList) Stream(java.util.stream.Stream) OpenIDClientRepository(oidc.repository.OpenIDClientRepository) Scope(oidc.model.Scope) Log(org.apache.commons.logging.Log) ResponseEntity(org.springframework.http.ResponseEntity) LogFactory(org.apache.commons.logging.LogFactory) Authentication(org.springframework.security.core.Authentication) UnsupportedEncodingException(java.io.UnsupportedEncodingException) RefreshToken(oidc.model.RefreshToken) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) OpenIDClient(oidc.model.OpenIDClient) RefreshToken(oidc.model.RefreshToken) Scope(oidc.model.Scope) Collectors.toList(java.util.stream.Collectors.toList)

Example 2 with RefreshToken

use of oidc.model.RefreshToken in project OpenConext-oidcng by OpenConext.

the class RefreshTokenRepositoryTest method findByJwtId.

@Test
public void findByJwtId() {
    String jwtId = UUID.randomUUID().toString();
    RefreshToken refreshToken = refreshTokenWithValue(jwtId);
    subject.insert(refreshToken);
    RefreshToken token = subject.findByJwtId(jwtId).get();
    assertEquals(jwtId, token.getJwtId());
}
Also used : RefreshToken(oidc.model.RefreshToken) Test(org.junit.Test) AbstractIntegrationTest(oidc.AbstractIntegrationTest)

Example 3 with RefreshToken

use of oidc.model.RefreshToken in project OpenConext-oidcng by OpenConext.

the class TokenEndpoint method handleRefreshCodeGrant.

private ResponseEntity handleRefreshCodeGrant(RefreshTokenGrant refreshTokenGrant, OpenIDClient client) throws java.text.ParseException {
    String refreshTokenValue = refreshTokenGrant.getRefreshToken().getValue();
    RefreshToken refreshToken;
    SignedJWT signedJWT = null;
    boolean oldFormat = uuidPattern.matcher(refreshTokenValue).matches();
    if (oldFormat) {
        // Old refreshToken
        refreshToken = refreshTokenRepository.findByInnerValue(refreshTokenValue);
    } else {
        Optional<SignedJWT> optionalSignedJWT = tokenGenerator.parseAndValidateSignedJWT(refreshTokenValue);
        signedJWT = optionalSignedJWT.orElseThrow(() -> new UnauthorizedException("Invalid refresh_token value"));
        String jwtId = signedJWT.getJWTClaimsSet().getJWTID();
        refreshToken = refreshTokenRepository.findByJwtId(jwtId).orElseThrow(() -> new IllegalArgumentException("RefreshToken not found"));
    }
    if (!refreshToken.getClientId().equals(client.getClientId())) {
        throw new InvalidClientException("Client is not authorized for the refresh token");
    }
    if (refreshToken.isExpired(Clock.systemDefaultZone())) {
        throw new UnauthorizedException("Refresh token expired");
    }
    // New tokens will be issued
    refreshTokenRepository.delete(refreshToken);
    // It is possible that the access token is already removed by cron cleanup actions
    Optional<AccessToken> accessToken;
    if (oldFormat) {
        // It is possible that the access token is already removed by cron cleanup actions
        accessToken = accessTokenRepository.findOptionalAccessTokenByValue(refreshToken.getAccessTokenValue());
    } else {
        accessToken = accessTokenRepository.findById(refreshToken.getAccessTokenId());
    }
    accessToken.ifPresent(accessTokenRepository::delete);
    Optional<User> optionalUser;
    if (refreshToken.isClientCredentials()) {
        optionalUser = Optional.empty();
    } else if (oldFormat) {
        optionalUser = Optional.of(tokenGenerator.decryptAccessTokenWithEmbeddedUserInfo(refreshToken.getAccessTokenValue()));
    } else {
        optionalUser = Optional.of(tokenGenerator.decryptAccessTokenWithEmbeddedUserInfo(signedJWT));
    }
    Map<String, Object> body = tokenEndpointResponse(optionalUser, client, refreshToken.getScopes(), Collections.emptyList(), false, null, optionalUser.map(User::getUpdatedAt), Optional.empty());
    return new ResponseEntity<>(body, responseHttpHeaders, HttpStatus.OK);
}
Also used : User(oidc.model.User) SignedJWT(com.nimbusds.jwt.SignedJWT) ResponseEntity(org.springframework.http.ResponseEntity) RefreshToken(oidc.model.RefreshToken) AccessToken(oidc.model.AccessToken) UnauthorizedException(oidc.exceptions.UnauthorizedException) InvalidClientException(oidc.exceptions.InvalidClientException)

Example 4 with RefreshToken

use of oidc.model.RefreshToken in project OpenConext-oidcng by OpenConext.

the class TokenEndpoint method tokenEndpointResponse.

private Map<String, Object> tokenEndpointResponse(Optional<User> user, OpenIDClient client, List<String> scopes, List<String> idTokenClaims, boolean clientCredentials, String nonce, Optional<Long> authorizationTime, Optional<String> authorizationCodeId) {
    Map<String, Object> map = new LinkedHashMap<>();
    EncryptedTokenValue encryptedAccessToken = user.map(u -> tokenGenerator.generateAccessTokenWithEmbeddedUserInfo(u, client, scopes)).orElse(tokenGenerator.generateAccessToken(client, scopes));
    String sub = user.map(User::getSub).orElse(client.getClientId());
    String unspecifiedUrnHash = user.map(u -> KeyGenerator.oneWayHash(u.getUnspecifiedNameId(), this.salt)).orElse(null);
    AccessToken accessToken = new AccessToken(encryptedAccessToken.getJwtId(), sub, client.getClientId(), scopes, encryptedAccessToken.getKeyId(), accessTokenValidity(client), !user.isPresent(), authorizationCodeId.orElse(null), unspecifiedUrnHash);
    accessToken = accessTokenRepository.insert(accessToken);
    map.put("access_token", encryptedAccessToken.getValue());
    map.put("token_type", "Bearer");
    if (client.getGrants().contains(GrantType.REFRESH_TOKEN.getValue())) {
        EncryptedTokenValue encryptedRefreshToken = user.map(u -> tokenGenerator.generateRefreshTokenWithEmbeddedUserInfo(u, client)).orElse(tokenGenerator.generateRefreshToken(client));
        String refreshTokenValue = encryptedRefreshToken.getValue();
        refreshTokenRepository.insert(new RefreshToken(encryptedRefreshToken.getJwtId(), accessToken, refreshTokenValidity(client)));
        map.put("refresh_token", refreshTokenValue);
    }
    map.put("expires_in", client.getAccessTokenValidity());
    if (isOpenIDRequest(scopes) && !clientCredentials) {
        TokenValue tokenValue = tokenGenerator.generateIDTokenForTokenEndpoint(user, client, nonce, idTokenClaims, scopes, authorizationTime);
        map.put("id_token", tokenValue.getValue());
    }
    return map;
}
Also used : AuthorizationCodeRepository(oidc.repository.AuthorizationCodeRepository) CodeVerifierMissingException(oidc.exceptions.CodeVerifierMissingException) Date(java.util.Date) JOSEException(com.nimbusds.jose.JOSEException) ClientAuthentication(com.nimbusds.oauth2.sdk.auth.ClientAuthentication) User(oidc.model.User) MACVerifier(com.nimbusds.jose.crypto.MACVerifier) RefreshTokenGrant(com.nimbusds.oauth2.sdk.RefreshTokenGrant) Map(java.util.Map) ClientSecretJWT(com.nimbusds.oauth2.sdk.auth.ClientSecretJWT) CodeVerifier(com.nimbusds.oauth2.sdk.pkce.CodeVerifier) PostMapping(org.springframework.web.bind.annotation.PostMapping) APPLICATION_JSON(org.apache.http.entity.ContentType.APPLICATION_JSON) HttpHeaders(org.springframework.http.HttpHeaders) MediaType(org.springframework.http.MediaType) SignedJWT(com.nimbusds.jwt.SignedJWT) RestController(org.springframework.web.bind.annotation.RestController) Collectors(java.util.stream.Collectors) TokenRequest(com.nimbusds.oauth2.sdk.TokenRequest) List(java.util.List) OpenIDClientRepository(oidc.repository.OpenIDClientRepository) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) Scope(oidc.model.Scope) Optional(java.util.Optional) TokenGenerator(oidc.secure.TokenGenerator) LogFactory(org.apache.commons.logging.LogFactory) Pattern(java.util.regex.Pattern) JWTAuthentication(com.nimbusds.oauth2.sdk.auth.JWTAuthentication) CodeChallengeMethod(com.nimbusds.oauth2.sdk.pkce.CodeChallengeMethod) AuthorizationCode(oidc.model.AuthorizationCode) BadCredentialsException(org.springframework.security.authentication.BadCredentialsException) GrantType(com.nimbusds.oauth2.sdk.GrantType) MessageDigest(java.security.MessageDigest) ServletUtils(com.nimbusds.oauth2.sdk.http.ServletUtils) JWTClaimsSet(com.nimbusds.jwt.JWTClaimsSet) RedirectMismatchException(oidc.exceptions.RedirectMismatchException) JWTAuthorizationGrantsException(oidc.exceptions.JWTAuthorizationGrantsException) UnknownClientException(oidc.exceptions.UnknownClientException) RefreshTokenRepository(oidc.repository.RefreshTokenRepository) Value(org.springframework.beans.factory.annotation.Value) LinkedHashMap(java.util.LinkedHashMap) CodeChallenge(com.nimbusds.oauth2.sdk.pkce.CodeChallenge) KeyGenerator(oidc.crypto.KeyGenerator) HttpServletRequest(javax.servlet.http.HttpServletRequest) TokenValue(oidc.model.TokenValue) InvalidClientException(oidc.exceptions.InvalidClientException) ParseException(com.nimbusds.oauth2.sdk.ParseException) PlainClientSecret(com.nimbusds.oauth2.sdk.auth.PlainClientSecret) OpenIDClient(oidc.model.OpenIDClient) MDCContext(oidc.log.MDCContext) JWTRequest(oidc.secure.JWTRequest) ClientCredentialsGrant(com.nimbusds.oauth2.sdk.ClientCredentialsGrant) HTTPRequest(com.nimbusds.oauth2.sdk.http.HTTPRequest) AuthorizationGrant(com.nimbusds.oauth2.sdk.AuthorizationGrant) AuthorizationCodeGrant(com.nimbusds.oauth2.sdk.AuthorizationCodeGrant) TokenAlreadyUsedException(oidc.exceptions.TokenAlreadyUsedException) InvalidGrantException(oidc.exceptions.InvalidGrantException) IOException(java.io.IOException) CertificateException(java.security.cert.CertificateException) AccessTokenRepository(oidc.repository.AccessTokenRepository) EncryptedTokenValue(oidc.model.EncryptedTokenValue) UserRepository(oidc.repository.UserRepository) HttpStatus(org.springframework.http.HttpStatus) AccessToken(oidc.model.AccessToken) BadJOSEException(com.nimbusds.jose.proc.BadJOSEException) UnauthorizedException(oidc.exceptions.UnauthorizedException) Clock(java.time.Clock) Log(org.apache.commons.logging.Log) ResponseEntity(org.springframework.http.ResponseEntity) NoSuchProviderException(java.security.NoSuchProviderException) Collections(java.util.Collections) AuthorizationEndpoint.validateScopes(oidc.endpoints.AuthorizationEndpoint.validateScopes) RefreshToken(oidc.model.RefreshToken) RefreshToken(oidc.model.RefreshToken) AccessToken(oidc.model.AccessToken) EncryptedTokenValue(oidc.model.EncryptedTokenValue) LinkedHashMap(java.util.LinkedHashMap) TokenValue(oidc.model.TokenValue) EncryptedTokenValue(oidc.model.EncryptedTokenValue)

Example 5 with RefreshToken

use of oidc.model.RefreshToken in project OpenConext-oidcng by OpenConext.

the class KeyRolloverTest method rolloverSigningKeysWithRemainingRefreshTokens.

@Test
public void rolloverSigningKeysWithRemainingRefreshTokens() throws GeneralSecurityException, ParseException, IOException {
    resetAndCreateSigningKeys(3);
    final List<String> signingKeys = mongoTemplate.findAll(SigningKey.class).stream().map(SigningKey::getKeyId).sorted().collect(toList());
    assertEquals(3, signingKeys.size());
    List<RefreshToken> tokens = Arrays.asList(refreshToken(signingKeys.get(0)));
    mongoTemplate.bulkOps(BulkOperations.BulkMode.ORDERED, RefreshToken.class).remove(new Query()).insert(tokens).execute();
    KeyRollover keyRollover = new KeyRollover(tokenGenerator, mongoTemplate, true, sequenceRepository);
    keyRollover.rollover();
    List<String> keys = mongoTemplate.findAll(SigningKey.class).stream().map(SigningKey::getKeyId).sorted().collect(toList());
    // Because of the keyRollover there is a new signing key and two are removed, because no token references, hence 2 remain
    assertEquals(2, keys.size());
    assertTrue(keys.contains(signingKeys.get(0)));
    assertFalse(keys.contains(signingKeys.get(1)));
    assertFalse(keys.contains(signingKeys.get(2)));
}
Also used : RefreshToken(oidc.model.RefreshToken) Query(org.springframework.data.mongodb.core.query.Query) SigningKey(oidc.model.SigningKey) Test(org.junit.Test) AbstractIntegrationTest(oidc.AbstractIntegrationTest)

Aggregations

RefreshToken (oidc.model.RefreshToken)6 AbstractIntegrationTest (oidc.AbstractIntegrationTest)3 AccessToken (oidc.model.AccessToken)3 Test (org.junit.Test)3 ResponseEntity (org.springframework.http.ResponseEntity)3 SignedJWT (com.nimbusds.jwt.SignedJWT)2 InvalidClientException (oidc.exceptions.InvalidClientException)2 UnauthorizedException (oidc.exceptions.UnauthorizedException)2 User (oidc.model.User)2 JOSEException (com.nimbusds.jose.JOSEException)1 MACVerifier (com.nimbusds.jose.crypto.MACVerifier)1 BadJOSEException (com.nimbusds.jose.proc.BadJOSEException)1 JWTClaimsSet (com.nimbusds.jwt.JWTClaimsSet)1 AuthorizationCodeGrant (com.nimbusds.oauth2.sdk.AuthorizationCodeGrant)1 AuthorizationGrant (com.nimbusds.oauth2.sdk.AuthorizationGrant)1 ClientCredentialsGrant (com.nimbusds.oauth2.sdk.ClientCredentialsGrant)1 GrantType (com.nimbusds.oauth2.sdk.GrantType)1 ParseException (com.nimbusds.oauth2.sdk.ParseException)1 RefreshTokenGrant (com.nimbusds.oauth2.sdk.RefreshTokenGrant)1 TokenRequest (com.nimbusds.oauth2.sdk.TokenRequest)1