-
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 13 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
94 changes: 94 additions & 0 deletions
94
...com/azure/spring/aad/resource/server/AzureActiveDirectoryResourceServerConfiguration.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.aad.resource.server; | ||
|
|
||
|
|
||
| import com.azure.spring.aad.implementation.AzureActiveDirectoryProperties; | ||
| import com.azure.spring.aad.implementation.IdentityEndpoints; | ||
| import com.azure.spring.aad.resource.server.validator.AzureJwtAudienceValidator; | ||
| import com.azure.spring.aad.resource.server.validator.AzureJwtIssuerValidator; | ||
| 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.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({AzureActiveDirectoryProperties.class}) | ||
| @ConditionalOnClass(BearerTokenAuthenticationToken.class) | ||
| public class AzureActiveDirectoryResourceServerConfiguration { | ||
|
|
||
| @Autowired | ||
| private AzureActiveDirectoryProperties azureActiveDirectoryProperties; | ||
|
|
||
| /** | ||
| * Use JwkKeySetUri to create JwtDecoder | ||
| * | ||
| * @return JwtDecoder bean | ||
| */ | ||
| @Bean | ||
| @ConditionalOnMissingBean(JwtDecoder.class) | ||
| public JwtDecoder jwtDecoderByJwkKeySetUri() { | ||
| if (StringUtils.isEmpty(azureActiveDirectoryProperties.getTenantId())) { | ||
| azureActiveDirectoryProperties.setTenantId("common"); | ||
| } | ||
| IdentityEndpoints identityEndpoints = new IdentityEndpoints(azureActiveDirectoryProperties.getUri()); | ||
| NimbusJwtDecoder nimbusJwtDecoder = NimbusJwtDecoder | ||
| .withJwkSetUri(identityEndpoints.jwkSetEndpoint(azureActiveDirectoryProperties.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(azureActiveDirectoryProperties.getAppIdUri())) { | ||
| List<String> validAudiences = new ArrayList<>(); | ||
| validAudiences.add(azureActiveDirectoryProperties.getAppIdUri()); | ||
| validators.add(new AzureJwtAudienceValidator(validAudiences)); | ||
| } | ||
| validators.add(new AzureJwtIssuerValidator()); | ||
| 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()) | ||
| .oauth2ResourceServer() | ||
| .jwt() | ||
| .jwtAuthenticationConverter(new AzureJwtBearerTokenAuthenticationConverter()); | ||
| } | ||
| } | ||
| } | ||
|
|
54 changes: 54 additions & 0 deletions
54
...java/com/azure/spring/aad/resource/server/AzureJwtBearerTokenAuthenticationConverter.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,54 @@ | ||
| // Copyright (c) Microsoft Corporation. All rights reserved. | ||
| // Licensed under the MIT License. | ||
| package com.azure.spring.aad.resource.server; | ||
|
|
||
| import com.azure.spring.autoconfigure.aad.UserPrincipal; | ||
| import com.nimbusds.jose.JWSObject; | ||
| import com.nimbusds.jwt.JWTClaimsSet; | ||
| import com.nimbusds.jwt.JWTClaimsSet.Builder; | ||
| import java.text.ParseException; | ||
| import java.util.Collection; | ||
| import java.util.Map.Entry; | ||
| import org.slf4j.Logger; | ||
| import org.slf4j.LoggerFactory; | ||
| import org.springframework.core.convert.converter.Converter; | ||
| import org.springframework.security.authentication.AbstractAuthenticationToken; | ||
| import org.springframework.security.core.GrantedAuthority; | ||
| import org.springframework.security.oauth2.core.OAuth2AccessToken; | ||
| import org.springframework.security.oauth2.jwt.Jwt; | ||
| import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter; | ||
| import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken; | ||
|
|
||
| /** | ||
| * A {@link Converter} that takes a {@link Jwt} and converts it into a {@link PreAuthenticatedAuthenticationToken}. | ||
| */ | ||
| public class AzureJwtBearerTokenAuthenticationConverter implements Converter<Jwt, AbstractAuthenticationToken> { | ||
|
|
||
| private static final Logger LOGGER = LoggerFactory.getLogger(AzureJwtBearerTokenAuthenticationConverter.class); | ||
| private final JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter(); | ||
|
|
||
| public AzureJwtBearerTokenAuthenticationConverter() { | ||
| } | ||
|
|
||
| @Override | ||
| public AbstractAuthenticationToken convert(Jwt jwt) { | ||
| OAuth2AccessToken accessToken = new OAuth2AccessToken( | ||
| OAuth2AccessToken.TokenType.BEARER, jwt.getTokenValue(), jwt.getIssuedAt(), jwt.getExpiresAt()); | ||
| AbstractAuthenticationToken token = this.jwtAuthenticationConverter.convert(jwt); | ||
| Collection<GrantedAuthority> authorities = token.getAuthorities(); | ||
| JWTClaimsSet.Builder builder = new Builder(); | ||
| for (Entry<String, Object> entry : jwt.getClaims().entrySet()) { | ||
| builder.claim(entry.getKey(), entry.getValue()); | ||
| } | ||
| JWTClaimsSet jwtClaimsSet = builder.build(); | ||
| JWSObject jwsObject = null; | ||
| try { | ||
| jwsObject = JWSObject.parse(accessToken.getTokenValue()); | ||
| } catch (ParseException e) { | ||
| LOGGER.error( | ||
|
saragluna marked this conversation as resolved.
Outdated
|
||
| e.getMessage() + ". When create an instance of JWSObject, an exception is resolved on the token."); | ||
| } | ||
| UserPrincipal userPrincipal = new UserPrincipal(accessToken.getTokenValue(), jwsObject, jwtClaimsSet); | ||
| return new PreAuthenticatedAuthenticationToken(userPrincipal, null, authorities); | ||
| } | ||
| } | ||
6 changes: 6 additions & 0 deletions
6
...ng/azure-spring-boot/src/main/java/com/azure/spring/aad/resource/server/package-info.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,6 @@ | ||
| // Copyright (c) Microsoft Corporation. All rights reserved. | ||
| // Licensed under the MIT License. | ||
| /** | ||
| * Package com.azure.spring.aad.resource.server | ||
| */ | ||
| package com.azure.spring.aad.resource.server; |
41 changes: 41 additions & 0 deletions
41
...c/main/java/com/azure/spring/aad/resource/server/validator/AzureJwtAudienceValidator.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,41 @@ | ||
| // Copyright (c) Microsoft Corporation. All rights reserved. | ||
| // Licensed under the MIT License. | ||
| package com.azure.spring.aad.resource.server.validator; | ||
|
|
||
| import com.azure.spring.autoconfigure.aad.AADTokenClaim; | ||
| 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 AzureJwtAudienceValidator implements OAuth2TokenValidator<Jwt> { | ||
|
|
||
| private final JwtClaimValidator<List<String>> validator; | ||
|
|
||
| /** | ||
| * Constructs a {@link AzureJwtAudienceValidator} using the provided parameters | ||
| * | ||
| * @param audiences - The audience that each {@link Jwt} should have. | ||
| */ | ||
| @SuppressWarnings({"unchecked", "rawtypes"}) | ||
| public AzureJwtAudienceValidator(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); | ||
| } | ||
|
|
||
|
|
||
| } |
51 changes: 51 additions & 0 deletions
51
...src/main/java/com/azure/spring/aad/resource/server/validator/AzureJwtIssuerValidator.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,51 @@ | ||
| // Copyright (c) Microsoft Corporation. All rights reserved. | ||
| // Licensed under the MIT License. | ||
| package com.azure.spring.aad.resource.server.validator; | ||
|
|
||
| import com.azure.spring.autoconfigure.aad.AADTokenClaim; | ||
| 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 AzureJwtIssuerValidator 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 final JwtClaimValidator<String> validator; | ||
|
|
||
| /** | ||
| * Constructs a {@link AzureJwtIssuerValidator} using the provided parameters | ||
| */ | ||
| @SuppressWarnings({"unchecked", "rawtypes"}) | ||
| public AzureJwtIssuerValidator() { | ||
| this.validator = new JwtClaimValidator(AADTokenClaim.ISS, validIssuer()); | ||
| } | ||
|
|
||
| private Predicate<String> validIssuer() { | ||
| return iss -> { | ||
| if (iss == null) { | ||
| return false; | ||
| } | ||
| return iss.startsWith(LOGIN_MICROSOFT_ONLINE_ISSUER) | ||
| || iss.startsWith(STS_WINDOWS_ISSUER) | ||
| || iss.startsWith(STS_CHINA_CLOUD_API_ISSUER); | ||
| }; | ||
| } | ||
|
|
||
| /** | ||
| * {@inheritDoc} | ||
| */ | ||
| @Override | ||
| public OAuth2TokenValidatorResult validate(Jwt token) { | ||
| Assert.notNull(token, "token cannot be null"); | ||
| return this.validator.validate(token); | ||
| } | ||
|
|
||
| } |
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
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change this doc.