spring-projects / spring-projects/spring-security

`OidcAuthorizationCodeAuthenticationProvider` is missing a `FactorGrantedAuthority`

Open
#19,140 5 comments 8 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

status: waiting-for-triage type: bug
Dominant language
Java
Stars
9.6k
Forks
6.3k
Avg merge
2d 11h
Merged PRs (30d)
52

Description

Describe the bug
OidcAuthorizationCodeAuthenticationProvider is missing a FactorGrantedAuthority (similarly to OAuth2LoginAuthenticationProvider), which is causing issues later in the chain (when, in a Spring Authorization Server, we try to generate an id_token for a grant_type=authorization_code)

To Reproduce
The bug started to appear in Spring Security 7.0.5 (I traced it to this issue: https://github.com/spring-projects/spring-security/issues/18282)

  1. Configure "OAuth2 Login" for our Spring Project (http.oauth2Login(...) — vanilla configuration)
    a. In your OAuth2 client configuration, set the scope openid email profile (for a Google OAuth2 client for example)
  2. Configure an Authorization Server http.oauth2AuthorizationServer(...) (vanilla should be fine too)
  3. Try to get an access_token + id_token from our local Authorization Server using a grant_type=authorization_code and scope=openid, by using our OAuth2 login configured (e.g. Google Login)

Expected behavior
Be able to retrieve an id_token + access_token.
But we are observing an API error indicating that auth_time cannot be null (because of the missing FactorGrantedAuthority that makes it way up to JwtGenerator, that is now (rightfully) awaiting a FactorGrantedAuthority to accurately compute the auth_time claim

Sample

Please find attached a screenshot of my debugger, just before that the JwtGenerator throws me an error because of the missing FactorGrantedAuthority
Image

Mitigation / short term fix

While waiting the long term solution (c.f. the PR associated with this issue):

Inject a GrantedAuthoritiesMapper into OidcAuthorizationCodeAuthenticationProvider that is injecting FactorGrantedAuthority.AUTHORIZATION_CODE_AUTHORITY for us:

    @Bean
    public SecurityFilterChain defaultSecurityFilterChain() {
        // ...
        http.oauth2Login(oauth2Login ->
            // ...
            oauth2Login.userInfoEndpoint(userInfo -> userInfo.userAuthoritiesMapper(bugFixOidcUserAuthoritiesMapper()))
            // ...
        );
        // ...
    }

    // TODO remove once Spring Security 7.X contains the long term fix
    private GrantedAuthoritiesMapper bugFixOidcUserAuthoritiesMapper() {
        return authorities -> {
            Set<GrantedAuthority> mapped = new LinkedHashSet<>(authorities);
            mapped.add(FactorGrantedAuthority.fromAuthority(FactorGrantedAuthority.AUTHORIZATION_CODE_AUTHORITY));
            return mapped;
        };
    }

On a final note, thanks a lot for your work guys ! 😄 🙏

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by locating OidcAuthorizationCodeAuthenticationProvider and comparing its authority handling with OAuth2LoginAuthenticationProvider. Trace how the resulting authorities reach JwtGenerator, then verify that an authorization_code flow can produce both an access_token and id_token without the auth_time error.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, spring
Domain
authentication, authorization, security
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.