복붙노트

[SPRING] Spring OAuth2 - 토큰 저장소에 수동으로 액세스 토큰 생성

SPRING

Spring OAuth2 - 토큰 저장소에 수동으로 액세스 토큰 생성

나는 자신이 접근 토큰을 만들고자하는 상황이있다. 나는 이런 것을 생각해 냈다.

@Inject
private DefaultTokenServices defaultTokenServices;

... 

OAuth2Authentication auth = xxx;
OAuth2AccessToken  token = defaultTokenServices.createAccessToken(auth);

유일한 문제는 OAuth2Authentication (내 코드에서 xxx가있는 부분)을 만드는 방법을 모르겠다는 것입니다. 사용자 및 고객 정보가 있으며이 토큰을 부여 할 권한을 알고 있습니다.

해결법

  1. ==============================

    1.여기에서 사용 사례는 사용중인 흐름에 따라 약간 다를 수 있습니다. 이것이 암호 부여 흐름에서 작동하는 것입니다. 토큰 저장소, 토큰 향상 프로그램 등 몇 가지 사용자 지정 클래스가 있습니다. 하지만 이것은 실제로 우리 자신의 필요에 맞게 수정 된 스프링 클래스의 확장 된 버전입니다.

    여기에서 사용 사례는 사용중인 흐름에 따라 약간 다를 수 있습니다. 이것이 암호 부여 흐름에서 작동하는 것입니다. 토큰 저장소, 토큰 향상 프로그램 등 몇 가지 사용자 지정 클래스가 있습니다. 하지만 이것은 실제로 우리 자신의 필요에 맞게 수정 된 스프링 클래스의 확장 된 버전입니다.

            HashMap<String, String> authorizationParameters = new HashMap<String, String>();
            authorizationParameters.put("scope", "read");
            authorizationParameters.put("username", "mobile_client");
            authorizationParameters.put("client_id", "mobile-client");
            authorizationParameters.put("grant", "password");
    
            DefaultAuthorizationRequest authorizationRequest = new DefaultAuthorizationRequest(authorizationParameters);
            authorizationRequest.setApproved(true);
    
            Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
            authorities.add(new SimpleGrantedAuthority("ROLE_UNTRUSTED_CLIENT"));
            authorizationRequest.setAuthorities(authorities);
    
            HashSet<String> resourceIds = new HashSet<String>();
            resourceIds.add("mobile-public");
            authorizationRequest.setResourceIds(resourceIds);
    
            // Create principal and auth token
            User userPrincipal = new User(user.getUserID(), "", true, true, true, true, authorities);
    
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userPrincipal, null, authorities) ;
    
            OAuth2Authentication authenticationRequest = new OAuth2Authentication(authorizationRequest, authenticationToken);
            authenticationRequest.setAuthenticated(true);
    
            CustomTokenStore tokenStore = new CustomTokenStore();
    
            // Token Enhancer
            CustomTokenEnhancer tokenEnhancer = new CustomTokenEnhancer(user.getUserID());
    
            CustomTokenServices tokenServices = new CustomTokenServices();
            tokenServices.setTokenEnhancer(tokenEnhancer);
            tokenServices.setSupportRefreshToken(true);
            tokenServices.setTokenStore(tokenStore);
    
            OAuth2AccessToken accessToken = tokenServices.createAccessTokenForUser(authenticationRequest, user);
    
  2. ==============================

    2.다음은 TokenEndpoint 인터페이스를 사용하여 토큰을 생성하는 방법입니다 (REST 서비스를 노출하는 데 사용됨).

    다음은 TokenEndpoint 인터페이스를 사용하여 토큰을 생성하는 방법입니다 (REST 서비스를 노출하는 데 사용됨).

    @Inject
    private TokenEndpoint tokenEndpoint;
    
    public ResponseEntity<?> getToken(Principal principal) {
    
            HashMap<String, String> parameters = new HashMap<String, String>();
            parameters.put("client_id", "appid");
            parameters.put("client_secret", "myOAuthSecret");
            parameters.put("grant_type", "password");
            parameters.put("password", myUser.getPassword());
            parameters.put("scope", "read write");
            parameters.put("username", myUser.getLogin());
    
            return tokenEndpoint.getAccessToken(principal, parameters);
    }
    
  3. ==============================

    3.다른 방법으로 OAuth2 액세스 토큰을 수동으로 생성하려면 TokenService 인스턴스를 사용할 수 있습니다.

    다른 방법으로 OAuth2 액세스 토큰을 수동으로 생성하려면 TokenService 인스턴스를 사용할 수 있습니다.

    @Autowired
    private AuthorizationServerEndpointsConfiguration configuration;
    
    @Override
    public String generateOAuth2AccessToken(User user, List<Role> roles, List<String> scopes) {
    
        Map<String, String> requestParameters = new HashMap<String, String>();
        Map<String, Serializable> extensionProperties = new HashMap<String, Serializable>();
    
        boolean approved = true;
        Set<String> responseTypes = new HashSet<String>();
        responseTypes.add("code");
    
        // Authorities
        List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
        for(Role role: roles)
            authorities.add(new SimpleGrantedAuthority("ROLE_" + role.getName()));
    
        OAuth2Request oauth2Request = new OAuth2Request(requestParameters, "clientIdTest", authorities, approved, new HashSet<String>(scopes), new HashSet<String>(Arrays.asList("resourceIdTest")), null, responseTypes, extensionProperties);
    
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user.getUsername(), "N/A", authorities);
    
        OAuth2Authentication auth = new OAuth2Authentication(oauth2Request, authenticationToken);
    
        AuthorizationServerTokenServices tokenService = configuration.getEndpointsConfigurer().getTokenServices();
    
        OAuth2AccessToken token = tokenService.createAccessToken(auth);
    
        return token.getValue();
    }
    
  4. ==============================

    4.이것은 나를 위해 일했다 :

    이것은 나를 위해 일했다 :

    @Override public OAuth2AccessToken getToken(String username, String password) {
        HashMap<String, String> parameters = new HashMap<String, String>();
        parameters.put("client_id", clientid);
        parameters.put("grant_type", "password");
        parameters.put("password", username);
        parameters.put("scope", scope);
        parameters.put("username", password);
    
        AuthorizationRequest authorizationRequest = defaultOAuth2RequestFactory.createAuthorizationRequest(parameters);
        authorizationRequest.setApproved(true);
    
        OAuth2Request oauth2Request = defaultOAuth2RequestFactory.createOAuth2Request(authorizationRequest);
        // Create principal and auth token
        final UsernamePasswordAuthenticationToken loginToken = new UsernamePasswordAuthenticationToken(
                username, password);
        Authentication authentication = authenticationManager.authenticate(loginToken);
    
        OAuth2Authentication authenticationRequest = new OAuth2Authentication(oauth2Request, authentication);
        authenticationRequest.setAuthenticated(true);
    
        OAuth2AccessToken accessToken = tokenServices.createAccessToken(authenticationRequest);
    
        return accessToken;
    }
    

    Oauth2Configuration에서 :

    @Bean
        DefaultOAuth2RequestFactory defaultOAuth2RequestFactory() {
        return new DefaultOAuth2RequestFactory(clientDetailsService);
    }
    

    Oauth2Configuration의 다른 부분은 다음 기사와 유사해야합니다.

    http://stytex.de/blog/2016/02/01/spring-cloud-security-with-oauth2/

  5. ==============================

    5.나는 Mop So 솔루션에 기반을 두었지만 대신 다음을 사용했다.

    나는 Mop So 솔루션에 기반을 두었지만 대신 다음을 사용했다.

    return tokenEndpoint.getAccessToken(principal, parameters);
    

    내가 사용 :

    tokenEndpoint.postAccessToken(principal, parameters);
    

    왜? tokenEndpoint.getAccessToken (principal, parameters)을 사용하면 endpoing은 GET 메소드로 호출되지 않았으므로 HttpRequestMethodNotSupportedException을 발생시킵니다. 최소한, 이것은 스프링 - 보안 - oauth2-2.0.13.RELEASE로 나에게 일어난 일이다.

    public OAuth2AccessToken getAccessToken() throws HttpRequestMethodNotSupportedException {
        HashMap<String, String> parameters = new HashMap<>();
        parameters.put("client_id", CLIENT_ID);
        parameters.put("client_secret", CLIENT_SECRET);
        parameters.put("grant_type", "client_credentials");
    
        ClientDetails clientDetails = clientDetailsStore.get(CLIENT_ID);
    
        // Create principal and auth token
        User userPrincipal = new User(CLIENT_ID, CLIENT_SECRET, true, true, true, true, clientDetails.getAuthorities());
    
        UsernamePasswordAuthenticationToken principal = new UsernamePasswordAuthenticationToken(userPrincipal, CLIENT_SECRET,
                clientDetails.getAuthorities());
    
        ResponseEntity<OAuth2AccessToken> accessToken = tokenEndpoint.postAccessToken(principal, parameters);
    
        return accessToken.getBody();
    }
    
  6. ==============================

    6.나는 여기에 나열된 모든 구현에 문제가있어서 마침내 국적없는 서버, oauth2 및 Google 소셜로 내 자신을 관리 할 수있었습니다. 여기에없는 튜토리얼의 마지막 부분

    나는 여기에 나열된 모든 구현에 문제가있어서 마침내 국적없는 서버, oauth2 및 Google 소셜로 내 자신을 관리 할 수있었습니다. 여기에없는 튜토리얼의 마지막 부분

    저를위한 문제는 Google oauth를 실행 한 후에, 나는 오래 살았던 토큰을위한 10 초 기간 토큰을 교환 할 필요가있다. 이를 위해서는 JWT 토큰을 생성하고 직접 생성 된 실제 액세스 토큰과 교환해야합니다.

    @Service
    class SocialTokenVerificationService {
    
        @Autowired
        private lateinit var jwsTokenService: JWSTokenService
        @Autowired
        private lateinit var clientDetailsService: ClientDetailsService
        @Autowired
        private lateinit var userService: UserService
        @Autowired
        private lateinit var tokenServices: DefaultTokenServices
        @Autowired
        private lateinit var tokenRequestFactory: OAuth2RequestFactory
    
        fun verifyToken(token: String): OAuth2AccessToken? {
            val claimSet = jwsTokenService.parseToken(token)
            val userDetails = userService.loadUserByUsername(claimSet.subject)
    
            val client = clientDetailsService.loadClientByClientId(DEFAULT_SERVER_CLIENT)
            val parameters = HashMap<String, String>()
            val authentication = UsernamePasswordAuthenticationToken(userDetails, null, userDetails.authorities)
            return tokenServices.createAccessToken(OAuth2Authentication(
                    tokenRequestFactory.createOAuth2Request(client, TokenRequest(parameters, client.clientId, listOf("read", "write"), "password")),
                    authentication
            ))
        }
    }
    

    이 모든 의존성으로 인해 데이터베이스에 저장되고 암호를 제공하지 않고 다른 것과 동일한 흐름을 따르는 토큰을 생성하기 위해 수행해야하는 작업은 다음과 같습니다.

    따라서 수동으로 토큰을 생성하는 방법을 요약하면 다음과 같습니다.

  7. from https://stackoverflow.com/questions/18536521/spring-oauth2-manually-creating-an-access-token-in-the-token-store by cc-by-sa and MIT license