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

Refactor implementation of AadOAuth2UserService #32595

Merged
merged 13 commits into from
Dec 16, 2022

Conversation

backwind1233
Copy link
Contributor

@backwind1233 backwind1233 commented Dec 14, 2022

Description

Refer to Design for implementation of OAuth2UserService for more details.

  1. Code implementation by design.
  2. Add unit tests for AadOAuth2UserService.

All SDK Contribution checklist:

  • The pull request does not introduce [breaking changes]
  • CHANGELOG is updated for new features, bug fixes or other significant changes.
  • I have read the contribution guidelines.

General Guidelines and Best Practices

  • Title of the pull request is clear and informative.
  • There are a small number of commits, each of which have an informative message. This means that previously merged commits do not appear in the history of the PR. For more information on cleaning up the commits in your PR, see this page.

Testing Guidelines

  • Pull request includes test coverage for the included changes.

@ghost ghost added the azure-spring All azure-spring related issues label Dec 14, 2022
@azure-sdk
Copy link
Collaborator

API change check

API changes are not detected in this pull request.

@backwind1233 backwind1233 changed the title draft Draft--refactor Dec 14, 2022
@backwind1233 backwind1233 changed the title Draft--refactor Draft--refactor AadOAuth2UserService# Dec 14, 2022
@backwind1233 backwind1233 changed the title Draft--refactor AadOAuth2UserService# Draft--refactor AadOAuth2UserService#loadUser Dec 14, 2022
@backwind1233 backwind1233 self-assigned this Dec 14, 2022
@backwind1233 backwind1233 changed the title Draft--refactor AadOAuth2UserService#loadUser Refactor implementation of AadOAuth2UserService Dec 15, 2022
@backwind1233 backwind1233 marked this pull request as ready for review December 15, 2022 02:54
@backwind1233 backwind1233 added the Client This issue points to a problem in the data-plane of the library. label Dec 15, 2022
@backwind1233 backwind1233 added this to the 2023-01 milestone Dec 15, 2022
}

/**
* Creates a new instance of {@link AadOAuth2UserService}.
*
* @param properties the AAD authentication properties
* @param graphClient the graph client
* @param restTemplateBuilder the restTemplateBuilder
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why deleting this?

}

private AadOAuth2UserService(AadAuthenticationProperties properties,
GraphClient graphClient) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

format

/**
* Tests for {@link AadOAuth2UserService}.
*/
public class AadOAuth2UserServiceTest {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no public

import java.util.Arrays;
import java.util.HashSet;

public final class TestOAuth2AccessTokens {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be an internal class?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, will do.

Comment on lines 209 to 214
public static OAuth2AccessToken noScopes() {
return new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "no-scopes", Instant.now(),
Instant.now().plus(Duration.ofDays(1)));
}

public static OAuth2AccessToken scopes(String... scopes) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need for public

class AadOAuth2UserServiceTest {
private ClientRegistration.Builder clientRegistrationBuilder;
private OidcIdToken idToken;
private AadOAuth2UserService aadOAuth2UserService;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems can be local variable

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think loadUserWithCustomAuthorities() is the special one.
Other test cases could leverage the code in setup().

Comment on lines 56 to 57
private GraphClient graphClient;
private AadAuthenticationProperties properties;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same for these two

Copy link
Contributor Author

@backwind1233 backwind1233 Dec 15, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made a little change.

idTokenClaims.put(StandardClaimNames.NAME, "user1");
idTokenClaims.put(StandardClaimNames.EMAIL, "user1@example.com");

this.idToken = new OidcIdToken("access-token", Instant.MIN, Instant.MAX, idTokenClaims);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems like this idToken isn't used by each test case, we can consider making this instantiated in each test method instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think loadUserWithCustomAuthorities() is the special one.
Other test cases could leverage the code in setup().

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If a variable is not fit for all cases, we should narrow the scope to method. It's okay to have some duplication in the UT. Which will make each test case easy to read.

private AadOAuth2UserService aadOAuth2UserService;
private OAuth2AccessToken accessToken;
private Map<String, Object> idTokenClaims = new HashMap<>();
private GraphClient graphClient;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same for this graph client

Comment on lines 118 to 121
if (authentication != null) {
LOGGER.debug("User {}'s authorities saved from session: {}.", authentication.getName(), authentication.getAuthorities());
return (DefaultOidcUser) session.getAttribute(DEFAULT_OIDC_USER);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not move this checking up to the top?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you make it more clear?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean the checking for authentication != null can be done early, like the below code:

public OidcUser loadUser(OidcUserRequest userRequest) throws OAuth2AuthenticationException {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication != null) {
            LOGGER.debug("User {}'s authorities saved from session: {}.", authentication.getName(), authentication.getAuthorities());
            return (DefaultOidcUser) session.getAttribute(DEFAULT_OIDC_USER);
        }

        ServletRequestAttributes attr = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
        HttpSession session = attr.getRequest().getSession(true);
        // ...
        return defaultOidcUser;
    }

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

We should get the session object first.

*/
@Override
public OidcUser loadUser(OidcUserRequest userRequest) throws OAuth2AuthenticationException {
// Delegate to the default implementation for loading a user
OidcUser oidcUser = oidcUserService.loadUser(userRequest);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This service is an extension for OidcUserService, if we remove the dependency of oidcUserService, it will not be a full Open ID Connect process that Spring Security implements. Some OAuth2AuthenticationExceptions will be ignored the new implementation will not throw OAuth2AuthenticationException .

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This service is an extension for OidcUserService

I think it's an implementation of OAuth2UserService.

if we remove the dependency of oidcUserService, it will not be a full Open ID Connect process that Spring Security implements.

Yes, there are differences between our implementation Spring Security .
What dou mean the Open ID Connect process?

Some OAuth2AuthenticationExceptions will be ignored the new implementation will not throw OAuth2AuthenticationException .

So, is there any problem?

@backwind1233 backwind1233 merged commit 71029d5 into Azure:main Dec 16, 2022
@backwind1233 backwind1233 deleted the aadoauth2userservice_gzh branch December 16, 2022 01:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
azure-spring All azure-spring related issues Client This issue points to a problem in the data-plane of the library.
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

[BUG] AadClientRegistrationRepository#toClientRegistration did not set userInfoUri
4 participants