Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consent scopes belong to multiple resource servers #9207

Closed
chenrujun opened this issue Nov 17, 2020 · 6 comments
Closed

Consent scopes belong to multiple resource servers #9207

chenrujun opened this issue Nov 17, 2020 · 6 comments
Assignees
Labels
for: stackoverflow A question that's better suited to stackoverflow.com

Comments

@chenrujun
Copy link
Contributor

Expected Behavior

In spring-security-oauth2-client,
when multiple clientRegistrations use the same provider,
by one user-consent operation,
resource owner can consent scopes belong to multiple resource servers ,
and put multiple authorizedClients into OAuth2AuthorizedClientRepository.

Current Behavior

when multiple clientRegistrations use the same provider,
by one user-consent operation,
resource owner can consent scopes belong to only one resource servers ,
and put only one authorizedClients into OAuth2AuthorizedClientRepository.

Context

For example, develop have clientRegistration1 and clientRegistration2, both client registration the use same provider.
We have the requirement to put both clientRegistration1 and clientRegistration2 by one consent operation.

Here is a workaround to satisfy this requirement: Azure/azure-sdk-for-java@5885067

@chenrujun chenrujun added status: waiting-for-triage An issue we've not yet triaged type: enhancement A general enhancement labels Nov 17, 2020
@chenrujun chenrujun changed the title Put multiple authorizedClient into OAuth2AuthorizedClientRepository with one user-consent operation consent scopes belong to multiple resource servers Nov 17, 2020
@chenrujun chenrujun changed the title consent scopes belong to multiple resource servers Consent scopes belong to multiple resource servers Nov 17, 2020
@jgrandja
Copy link
Contributor

Apologies @chenrujun, but I'm not understanding your use case.

Can you put together a minimal sample that demonstrates your use case so I can better understand.

@jgrandja jgrandja self-assigned this Nov 19, 2020
@jgrandja jgrandja added in: oauth2 An issue in OAuth2 modules (oauth2-core, oauth2-client, oauth2-resource-server, oauth2-jose) status: waiting-for-feedback We need additional information before we can continue and removed status: waiting-for-triage An issue we've not yet triaged type: enhancement A general enhancement labels Nov 19, 2020
@chenrujun
Copy link
Contributor Author

Hi, @jgrandja , Thank you for your response.

Here is the sample:
https://github.com/chenrujun/spring-security-issues-9207-sample/blob/master/src/main/resources/application.yml

spring:
  security:
    oauth2:
      client:
        provider:
          provider-one:
            authorization-uri: blabla
            token-uri: blabla
        registration:
          registration-one:
            provider: provider-one
            client-id: blabla
            client_secret: blabla
            scope: scope-one-one, scope-one-two
          registration-two:
            provider: provider-one
            client-id: blabla
            client_secret: blabla
            scope: scope-two-one, scope-two-two

In this configuration, registration-one and registration-two use the same provider: provider-one.
I need this function: after user login in provider-one's login page, both registration-one and registration-two exist in OAuth2AuthorizedClientRepository

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Nov 24, 2020
@jgrandja
Copy link
Contributor

@chenrujun The sample you provided does not qualify as a minimal reproducible sample. The only code in there is @SpringBootApplication and application.yml.

Either way, I now understand what you are trying to achieve.

The 2 options are as follows:

Option 1

Change application.yml to:

spring:
  security:
    oauth2:
      client:
        provider:
          provider-one:
            authorization-uri: blabla
            token-uri: blabla
        registration:
          registration-one:
            provider: provider-one
            client-id: blabla
            client_secret: blabla
            scope: scope-one-one, scope-one-two, scope-two-one, scope-two-two

After user is logged in then redirect to /authorize-client

@GetMapping("/authorize-client")
public String authorizeClient(
		@RegisteredOAuth2AuthorizedClient("registration-one") OAuth2AuthorizedClient authorizedClient) {

	return "index";
}

authorizedClient will have an access token with all scopes required: scope-one-one, scope-one-two, scope-two-one, scope-two-two

Option 2

Keep application.yml as-is:

spring:
  security:
    oauth2:
      client:
        provider:
          provider-one:
            authorization-uri: blabla
            token-uri: blabla
        registration:
          registration-one:
            provider: provider-one
            client-id: blabla
            client_secret: blabla
            scope: scope-one-one, scope-one-two
          registration-two:
            provider: provider-one
            client-id: blabla
            client_secret: blabla
            scope: scope-two-one, scope-two-two

After user is logged in then redirect to /authorize-two-clients

@GetMapping("/authorize-two-clients")
public String authorizeTwoClients(
		@RegisteredOAuth2AuthorizedClient("registration-one") OAuth2AuthorizedClient authorizedClient1,
		@RegisteredOAuth2AuthorizedClient("registration-two") OAuth2AuthorizedClient authorizedClient2) {

	return "index";
}

authorizedClient1 and authorizedClient2 are now available to call resource servers.

For future reference, questions are better suited to Stack Overflow. We prefer to use GitHub issues only for bugs and enhancements.

I'm going to close this as both solutions will work for your use case.

@jgrandja jgrandja added for: stackoverflow A question that's better suited to stackoverflow.com and removed in: oauth2 An issue in OAuth2 modules (oauth2-core, oauth2-client, oauth2-resource-server, oauth2-jose) status: feedback-provided Feedback has been provided labels Nov 26, 2020
@chenrujun
Copy link
Contributor Author

@jgrandja , Thank you for your response.


Option 1

This option can NOT solve my problem. Because in access_token, there is a claim named aud, which means audience.
One access_token can only have one audience:

  • scope-one-one, scope-one-two belongs to audience-one,
  • scope-two-one, scope-two-two belongs to audience-two,
    So we can NOT get access_token for the 4 scopes, because they belong to different audience.
    If we require an access_token for all the 4 scopes, the authorization server will return error like error scopes.

Refs:
https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow#request-an-access-token

The scopes must all be from a single resource

Option 2

This can NOT solve my problem.

  1. In this option, user need to input username & password 2 times. What I want is input username & password 1 time.
  2. In the OidcUser, it will have authorities of (SCOPE_scope-one-one, SCOPE_scope-one-two) or (SCOPE_scope-two-one, SCOPE_scope-two-two). It can not have all the authorities at the same time (SCOPE_scope-one-one, SCOPE_scope-one-two, SCOPE_scope-two-one, SCOPE_scope-two-two)

Refs:
https://github.com/spring-projects/spring-security/blob/5.4.0/oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/oidc/userinfo/OidcUserService.java#L134

@jgrandja
Copy link
Contributor

@chenrujun

Option 1 can work but you will need to configure the provider.

As per spec, the aud claim:

The "aud" (audience) claim identifies the recipients that the JWT is
intended for. Each principal intended to process the JWT MUST
identify itself with a value in the audience claim. If the principal
processing the claim does not identify itself with a value in the
"aud" claim when this claim is present, then the JWT MUST be
rejected. In the general case, the "aud" value is an array of case-
sensitive strings, each containing a StringOrURI value
. In the
special case when the JWT has one audience, the "aud" value MAY be a
single case-sensitive string containing a StringOrURI value. The
interpretation of audience values is generally application specific.
Use of this claim is OPTIONAL.

The aud claim could contain the identifiers for both resource servers. You will need to configure this with the provider you are using.

Option 2 can work as well.

user need to input username & password 2 times

I'm assuming you meant the consent screen comes up twice? If this is the case, then most providers support auto-approving scopes and/or not displaying the consent screen. Again, this is a provider configuration so you'll have to refer to the reference document on how to configure.

If in fact you did mean the user has to enter credentials twice then I find this very unusual. After the user authenticates with the provider the first time then the session is authenticated and should not re-authenticate on next attempt? Either way, this is also a configuration on the provider that you will need to look into.

Regardless, both options will work but looks like you need to apply some configuration on the provider side.

@chenrujun
Copy link
Contributor Author

@jgrandja

Regardless, both options will work but looks like you need to apply some configuration on the provider side.

I got it. Thank you very much for your suggestions. 👍


Hi, @lzc-1997-abel , could you please investigate whether Microsoft Identity support:

  1. Multiple audience in "aud" claim.
  2. Auto-approving scopes and/or not displaying the consent screen

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
for: stackoverflow A question that's better suited to stackoverflow.com
Projects
None yet
Development

No branches or pull requests

3 participants