-
Notifications
You must be signed in to change notification settings - Fork 2.2k
validate access token #17613
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
Merged
saragluna
merged 24 commits into
Azure:master
from
ZhuXiaoBing-cn:access_token_validate
Nov 30, 2020
Merged
validate access token #17613
Changes from 4 commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
29b5cd0
* Make changes according to checkstyle
ZhuXiaoBing-cn 081cb82
* Make changes according to checkstyle
ZhuXiaoBing-cn c8a3508
* Make changes according to checkstyle
ZhuXiaoBing-cn b9aa067
* add JavaDoc
ZhuXiaoBing-cn fdfb007
* remove tenant validator
ZhuXiaoBing-cn bddc2e4
* add Converter,it's effect will be to store the UserPrincipal to Aut…
ZhuXiaoBing-cn cb82a9b
Merge branch 'master' into access_token_validate
ZhuXiaoBing-cn 0732746
Merge branch 'master' into access_token_validate
ZhuXiaoBing-cn 3f8dac0
* update file name
ZhuXiaoBing-cn 4b6e974
* Make changes according to checkstyle
ZhuXiaoBing-cn ce65efe
Merge branch 'master' into access_token_validate
ZhuXiaoBing-cn 05d929d
* Make changes according to checkstyle
ZhuXiaoBing-cn 4e4d053
* Make changes according to checkstyle
ZhuXiaoBing-cn b362dfb
* Make changes according to checkstyle
ZhuXiaoBing-cn ae39fe7
* Make changes according to checkstyle
ZhuXiaoBing-cn acaeefa
* update AzureJwtBearerTokenAuthenticationConverter
ZhuXiaoBing-cn d25e9df
Merge branch 'master' into access_token_validate
ZhuXiaoBing-cn a31f1a6
* add AzureOAuth2AuthenticatedPrincipal
ZhuXiaoBing-cn f7aa628
Merge branch 'master' into access_token_validate
ZhuXiaoBing-cn 0851fc6
* update AzureActiveDirectoryResourceServerConfiguration
ZhuXiaoBing-cn 0ac20f9
* Make changes according to checkstyle
ZhuXiaoBing-cn 9f80db0
* Make changes according to checkstyle.
ZhuXiaoBing-cn fd2155b
* update unit test
ZhuXiaoBing-cn 7403602
* Modify invalid import
ZhuXiaoBing-cn File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
40 changes: 40 additions & 0 deletions
40
...spring-boot/src/main/java/com/azure/spring/autoconfigure/aad/AADJwtAudienceValidator.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| // Copyright (c) Microsoft Corporation. All rights reserved. | ||
| // Licensed under the MIT License. | ||
| package com.azure.spring.autoconfigure.aad; | ||
|
|
||
| import java.util.List; | ||
| import org.springframework.security.oauth2.core.OAuth2TokenValidator; | ||
| import org.springframework.security.oauth2.core.OAuth2TokenValidatorResult; | ||
| import org.springframework.security.oauth2.jwt.Jwt; | ||
| import org.springframework.security.oauth2.jwt.JwtClaimValidator; | ||
| import org.springframework.util.Assert; | ||
|
|
||
| /** | ||
| * Validates the "aud" claim in a {@link Jwt}, that is matches a configured value | ||
| */ | ||
| public class AADJwtAudienceValidator implements OAuth2TokenValidator<Jwt> { | ||
|
|
||
| private final JwtClaimValidator<List<String>> validator; | ||
|
|
||
| /** | ||
| * Constructs a {@link AADJwtAudienceValidator} using the provided parameters | ||
| * | ||
| * @param audiences - The audience that each {@link Jwt} should have. | ||
| */ | ||
| @SuppressWarnings({"unchecked", "rawtypes"}) | ||
| public AADJwtAudienceValidator(List<String> audiences) { | ||
| Assert.notNull(audiences, "audiences cannot be null"); | ||
| this.validator = new JwtClaimValidator(AADTokenClaim.AUD, aud -> audiences.containsAll((List<String>) aud)); | ||
| } | ||
|
|
||
| /** | ||
| * {@inheritDoc} | ||
| */ | ||
| @Override | ||
| public OAuth2TokenValidatorResult validate(Jwt token) { | ||
| Assert.notNull(token, "token cannot be null"); | ||
| return this.validator.validate(token); | ||
| } | ||
|
|
||
|
|
||
| } | ||
80 changes: 80 additions & 0 deletions
80
...e-spring-boot/src/main/java/com/azure/spring/autoconfigure/aad/AADJwtIssuerValidator.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,80 @@ | ||
| // Copyright (c) Microsoft Corporation. All rights reserved. | ||
| // Licensed under the MIT License. | ||
| package com.azure.spring.autoconfigure.aad; | ||
|
|
||
| import java.util.Set; | ||
| import java.util.function.Predicate; | ||
| import org.springframework.security.oauth2.core.OAuth2TokenValidator; | ||
| import org.springframework.security.oauth2.core.OAuth2TokenValidatorResult; | ||
| import org.springframework.security.oauth2.jwt.Jwt; | ||
| import org.springframework.security.oauth2.jwt.JwtClaimValidator; | ||
| import org.springframework.util.Assert; | ||
|
|
||
| /** | ||
| * Validates the "iss" claim in a {@link Jwt}, that is matches a configured value | ||
| */ | ||
| public class AADJwtIssuerValidator implements OAuth2TokenValidator<Jwt> { | ||
|
|
||
| private static final String LOGIN_MICROSOFT_ONLINE_ISSUER = "https://login.microsoftonline.com/"; | ||
| private static final String STS_WINDOWS_ISSUER = "https://sts.windows.net/"; | ||
| private static final String STS_CHINA_CLOUD_API_ISSUER = "https://sts.chinacloudapi.cn/"; | ||
| private static final String COMMON = "common"; | ||
|
saragluna marked this conversation as resolved.
Outdated
|
||
| private final JwtClaimValidator<String> validator; | ||
|
|
||
| /** | ||
| * Constructs a {@link AADJwtIssuerValidator} using the provided parameters | ||
| * | ||
| * @param tenantId - The tenant that each {@link Jwt} should have. | ||
| * @param allowedTenantIds - Multi-tenant is allowed tenantIds | ||
| */ | ||
| @SuppressWarnings({"unchecked", "rawtypes"}) | ||
| public AADJwtIssuerValidator(String tenantId, Set<String> allowedTenantIds) { | ||
| Assert.notNull(tenantId, "tenantId cannot be null"); | ||
| Assert.notNull(allowedTenantIds, "allowedTenantIds cannot be null"); | ||
| if (tenantId.equals(COMMON)) { | ||
| if (allowedTenantIds.isEmpty()) { | ||
| this.validator = new JwtClaimValidator(AADTokenClaim.ISS, iss -> true); | ||
| } else { | ||
| this.validator = new JwtClaimValidator(AADTokenClaim.ISS, validIssuer(allowedTenantIds)); | ||
| } | ||
| } else { | ||
| this.validator = new JwtClaimValidator(AADTokenClaim.ISS, validIssuer(tenantId)); | ||
| } | ||
| } | ||
|
|
||
| private Predicate<String> validIssuer(String tenantId) { | ||
| return tid -> { | ||
| if (tid.startsWith(LOGIN_MICROSOFT_ONLINE_ISSUER) || tid.startsWith(STS_WINDOWS_ISSUER) | ||
| || tid.startsWith(STS_CHINA_CLOUD_API_ISSUER)) { | ||
| if (tid.contains(tenantId)) { | ||
| return true; | ||
| } | ||
| } | ||
| return false; | ||
| }; | ||
| } | ||
|
|
||
| private Predicate<String> validIssuer(Set<String> allowedTenantIds) { | ||
| return tid -> { | ||
| if (tid.startsWith(LOGIN_MICROSOFT_ONLINE_ISSUER) || tid.startsWith(STS_WINDOWS_ISSUER) | ||
| || tid.startsWith(STS_CHINA_CLOUD_API_ISSUER)) { | ||
| for (String allowedTenantId : allowedTenantIds) { | ||
| if (tid.contains(allowedTenantId)) { | ||
| return true; | ||
| } | ||
| } | ||
| } | ||
| return false; | ||
| }; | ||
| } | ||
|
|
||
| /** | ||
| * {@inheritDoc} | ||
| */ | ||
| @Override | ||
| public OAuth2TokenValidatorResult validate(Jwt token) { | ||
| Assert.notNull(token, "token cannot be null"); | ||
| return this.validator.validate(token); | ||
| } | ||
|
|
||
| } | ||
50 changes: 50 additions & 0 deletions
50
...e-spring-boot/src/main/java/com/azure/spring/autoconfigure/aad/AADJwtTenantValidator.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| // Copyright (c) Microsoft Corporation. All rights reserved. | ||
| // Licensed under the MIT License. | ||
| package com.azure.spring.autoconfigure.aad; | ||
|
|
||
| import java.util.Set; | ||
| import org.springframework.security.oauth2.core.OAuth2TokenValidator; | ||
| import org.springframework.security.oauth2.core.OAuth2TokenValidatorResult; | ||
| import org.springframework.security.oauth2.jwt.Jwt; | ||
| import org.springframework.security.oauth2.jwt.JwtClaimValidator; | ||
| import org.springframework.util.Assert; | ||
|
|
||
| /** | ||
| * Validates the "tid" claim in a {@link Jwt}, that is matches a configured value | ||
| */ | ||
| public class AADJwtTenantValidator implements OAuth2TokenValidator<Jwt> { | ||
|
|
||
| private final JwtClaimValidator<String> validator; | ||
| private static final String COMMON = "common"; | ||
|
|
||
| /** | ||
| * Constructs a {@link AADJwtIssuerValidator} using the provided parameters | ||
| * | ||
| * @param tenantId - The tenant that each {@link Jwt} should have. | ||
| * @param allowedTenantIds - Multi-tenant is allowed tenantIds | ||
| */ | ||
| @SuppressWarnings({"unchecked", "rawtypes"}) | ||
| public AADJwtTenantValidator(String tenantId, Set<String> allowedTenantIds) { | ||
| Assert.notNull(tenantId, "tenantId cannot be null"); | ||
| Assert.notNull(allowedTenantIds, "allowedTenantIds cannot be null"); | ||
| if (tenantId.equals(COMMON)) { | ||
| if (allowedTenantIds.isEmpty()) { | ||
| this.validator = new JwtClaimValidator(AADTokenClaim.TID, tid -> true); | ||
| } else { | ||
| this.validator = new JwtClaimValidator(AADTokenClaim.TID, allowedTenantIds::contains); | ||
| } | ||
| } else { | ||
| this.validator = new JwtClaimValidator(AADTokenClaim.TID, tenantId::equals); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * {@inheritDoc} | ||
| */ | ||
| @Override | ||
| public OAuth2TokenValidatorResult validate(Jwt token) { | ||
| Assert.notNull(token, "token cannot be null"); | ||
| return this.validator.validate(token); | ||
| } | ||
|
|
||
| } |
94 changes: 94 additions & 0 deletions
94
.../src/main/java/com/azure/spring/autoconfigure/aad/AADResourceServerAutoConfiguration.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,94 @@ | ||
| // Copyright (c) Microsoft Corporation. All rights reserved. | ||
| // Licensed under the MIT License. | ||
| package com.azure.spring.autoconfigure.aad; | ||
|
|
||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.List; | ||
| import org.springframework.beans.factory.annotation.Autowired; | ||
| import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; | ||
| import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; | ||
| import org.springframework.boot.context.properties.EnableConfigurationProperties; | ||
| import org.springframework.context.annotation.Bean; | ||
| import org.springframework.context.annotation.Configuration; | ||
| import org.springframework.security.config.annotation.web.builders.HttpSecurity; | ||
| import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; | ||
| import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; | ||
| import org.springframework.security.config.annotation.web.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer; | ||
| import org.springframework.security.oauth2.core.DelegatingOAuth2TokenValidator; | ||
| import org.springframework.security.oauth2.core.OAuth2TokenValidator; | ||
| import org.springframework.security.oauth2.jwt.Jwt; | ||
| import org.springframework.security.oauth2.jwt.JwtDecoder; | ||
| import org.springframework.security.oauth2.jwt.JwtTimestampValidator; | ||
| import org.springframework.security.oauth2.jwt.NimbusJwtDecoder; | ||
| import org.springframework.security.oauth2.server.resource.BearerTokenAuthenticationToken; | ||
| import org.springframework.util.StringUtils; | ||
|
|
||
| /** | ||
| * <p> | ||
| * The configuration will not be activated if no {@link BearerTokenAuthenticationToken} class provided. | ||
| * <p> | ||
| * By default, creating a JwtDecoder through JwkKeySetUri will be auto-configured. | ||
| */ | ||
| @Configuration(proxyBeanMethods = false) | ||
| @EnableConfigurationProperties(AADAuthenticationProperties.class) | ||
| @ConditionalOnClass(BearerTokenAuthenticationToken.class) | ||
| public class AADResourceServerAutoConfiguration { | ||
|
|
||
| @Autowired | ||
| private AADAuthenticationProperties aadAuthenticationProperties; | ||
|
|
||
| /** | ||
| * Use JwkKeySetUri to create JwtDecoder | ||
| * | ||
| * @return JwtDecoder bean | ||
| */ | ||
| @Bean | ||
| @ConditionalOnMissingBean(JwtDecoder.class) | ||
| public JwtDecoder jwtDecoderByJwkKeySetUri() { | ||
| if (StringUtils.isEmpty(aadAuthenticationProperties.getTenantId())) { | ||
| aadAuthenticationProperties.setTenantId("common"); | ||
| } | ||
| AuthorizationServerEndpoints endpoints = new AuthorizationServerEndpoints(); | ||
| NimbusJwtDecoder nimbusJwtDecoder = NimbusJwtDecoder | ||
| .withJwkSetUri(endpoints.jwkSetEndpoint(aadAuthenticationProperties.getTenantId())).build(); | ||
| List<OAuth2TokenValidator<Jwt>> validators = createDefaultValidator(); | ||
| nimbusJwtDecoder.setJwtValidator(new DelegatingOAuth2TokenValidator<>(validators)); | ||
| return nimbusJwtDecoder; | ||
| } | ||
|
|
||
| public List<OAuth2TokenValidator<Jwt>> createDefaultValidator() { | ||
| List<OAuth2TokenValidator<Jwt>> validators = new ArrayList<>(); | ||
| if (!StringUtils.isEmpty(aadAuthenticationProperties.getClientId()) || !StringUtils | ||
| .isEmpty(aadAuthenticationProperties.getAppIdUri())) { | ||
| List<String> validAudiences = new ArrayList<>(); | ||
| validAudiences.add(aadAuthenticationProperties.getClientId()); | ||
| validAudiences.add(aadAuthenticationProperties.getAppIdUri()); | ||
| validators.add(new AADJwtAudienceValidator(validAudiences)); | ||
| } | ||
| validators.add(new AADJwtTenantValidator(aadAuthenticationProperties.getTenantId(), | ||
| aadAuthenticationProperties.getAllowedTenantIds())); | ||
| validators.add(new AADJwtIssuerValidator(aadAuthenticationProperties.getTenantId(), | ||
| aadAuthenticationProperties.getAllowedTenantIds())); | ||
| validators.add(new JwtTimestampValidator()); | ||
| return validators; | ||
| } | ||
|
|
||
| /** | ||
| * Default configuration class for using AAD authentication and authorization. User can write another configuration | ||
| * bean to override it. | ||
| */ | ||
| @Configuration | ||
| @ConditionalOnMissingBean(WebSecurityConfigurerAdapter.class) | ||
| @EnableWebSecurity | ||
| public static class DefaultAzureOAuth2ResourceServerWebSecurityConfigurerAdapter extends | ||
| WebSecurityConfigurerAdapter { | ||
|
|
||
| @Override | ||
| protected void configure(HttpSecurity http) throws Exception { | ||
| http.authorizeRequests((requests) -> requests.anyRequest().authenticated()); | ||
| http.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt); | ||
| } | ||
| } | ||
| } | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.