Search in sources :

Example 1 with TokenAlreadyUsedException

use of oidc.exceptions.TokenAlreadyUsedException in project OpenConext-oidcng by OpenConext.

the class TokenEndpoint method handleAuthorizationCodeGrant.

private ResponseEntity handleAuthorizationCodeGrant(AuthorizationCodeGrant authorizationCodeGrant, OpenIDClient client) {
    String code = authorizationCodeGrant.getAuthorizationCode().getValue();
    MDCContext.mdcContext("code", "code");
    AuthorizationCode authorizationCode = concurrentAuthorizationCodeRepository.findByCodeNotAlreadyUsedAndMarkAsUsed(code);
    if (authorizationCode == null) {
        /*
             * Now it become's tricky. Did we get an 'null' because the code was bogus or because it was already
             * used? To both satisfy the - highly theoretical - risk of the audit race condition and the OIDC certification
             * demand of deleting access_token issued with the re-used authorization code we need to query again.
             *
             * If they code was bogus this will result in a 404 exception by the authorizationCodeRepository#findByCode
             * and if we find something then we know there was a re-use issue.
             */
        AuthorizationCode byCode = authorizationCodeRepository.findByCode(code);
        accessTokenRepository.deleteByAuthorizationCodeId(byCode.getId());
        throw new TokenAlreadyUsedException("Authorization code already used");
    }
    if (!authorizationCode.getClientId().equals(client.getClientId())) {
        throw new UnauthorizedException("Client is not authorized for the authorization code");
    }
    if (authorizationCodeGrant.getRedirectionURI() != null && !authorizationCodeGrant.getRedirectionURI().toString().equals(authorizationCode.getRedirectUri())) {
        throw new RedirectMismatchException("Redirects do not match");
    }
    if (authorizationCode.isRedirectURIProvided() && authorizationCodeGrant.getRedirectionURI() == null) {
        throw new RedirectMismatchException("Redirect URI is mandatory if specified in code request");
    }
    if (authorizationCode.isExpired(Clock.systemDefaultZone())) {
        throw new UnauthorizedException("Authorization code expired");
    }
    CodeVerifier codeVerifier = authorizationCodeGrant.getCodeVerifier();
    String codeChallenge = authorizationCode.getCodeChallenge();
    if (codeVerifier != null) {
        if (codeChallenge == null) {
            throw new CodeVerifierMissingException("code_verifier present, but no code_challenge in the authorization_code");
        }
        CodeChallengeMethod codeChallengeMethod = CodeChallengeMethod.parse(authorizationCode.getCodeChallengeMethod());
        CodeChallenge computed = CodeChallenge.compute(codeChallengeMethod, codeVerifier);
        // Constant time comparison
        if (!MessageDigest.isEqual(codeChallenge.getBytes(), computed.getValue().getBytes())) {
            LOG.error(String.format("CodeVerifier %s with method %s does not match codeChallenge %s. Expected codeChallenge is %s", codeVerifier.getValue(), codeChallengeMethod, codeChallenge, computed.getValue()));
            throw new CodeVerifierMissingException("code_verifier does not match code_challenge");
        }
    }
    User user = userRepository.findUserBySub(authorizationCode.getSub());
    MDCContext.mdcContext(user);
    // User information is encrypted in access token
    LOG.debug("Deleting user " + user.getSub());
    userRepository.delete(user);
    Map<String, Object> body = tokenEndpointResponse(Optional.of(user), client, authorizationCode.getScopes(), authorizationCode.getIdTokenClaims(), false, authorizationCode.getNonce(), Optional.of(authorizationCode.getAuthTime()), Optional.of(authorizationCode.getId()));
    return new ResponseEntity<>(body, responseHttpHeaders, HttpStatus.OK);
}
Also used : AuthorizationCode(oidc.model.AuthorizationCode) User(oidc.model.User) CodeChallengeMethod(com.nimbusds.oauth2.sdk.pkce.CodeChallengeMethod) CodeVerifierMissingException(oidc.exceptions.CodeVerifierMissingException) TokenAlreadyUsedException(oidc.exceptions.TokenAlreadyUsedException) CodeVerifier(com.nimbusds.oauth2.sdk.pkce.CodeVerifier) ResponseEntity(org.springframework.http.ResponseEntity) UnauthorizedException(oidc.exceptions.UnauthorizedException) RedirectMismatchException(oidc.exceptions.RedirectMismatchException) CodeChallenge(com.nimbusds.oauth2.sdk.pkce.CodeChallenge)

Aggregations

CodeChallenge (com.nimbusds.oauth2.sdk.pkce.CodeChallenge)1 CodeChallengeMethod (com.nimbusds.oauth2.sdk.pkce.CodeChallengeMethod)1 CodeVerifier (com.nimbusds.oauth2.sdk.pkce.CodeVerifier)1 CodeVerifierMissingException (oidc.exceptions.CodeVerifierMissingException)1 RedirectMismatchException (oidc.exceptions.RedirectMismatchException)1 TokenAlreadyUsedException (oidc.exceptions.TokenAlreadyUsedException)1 UnauthorizedException (oidc.exceptions.UnauthorizedException)1 AuthorizationCode (oidc.model.AuthorizationCode)1 User (oidc.model.User)1 ResponseEntity (org.springframework.http.ResponseEntity)1