spring-security-oauth2-authorization-server client_secret_basic 认证模式

文章详细介绍了SpringSecurityOAuth2框架中client_secret_basic认证模式的工作流程,包括添加注册客户端、发送请求的方式(如使用IDEAHTTPRequest、curl和APIPost文档)、认证过程中的关键类(如OAuth2ClientAuthenticationFilter、ClientSecretBasicAuthenticationConverter和OAuth2TokenEndpointFilter)以及令牌的生成过程。整个流程涉及客户端认证、授权验证和令牌生成等多个环节。
摘要由CSDN通过智能技术生成

spring-security-oauth2-authorization-server client_secret_basic 认证模式

1.添加 RegisteredClient

class CLIENT_SECRET_BASIC extends AbstractClientTypeAuthorizationServerTests {
  /**
   * 添加测试注册客户端
   */
  private void addRegisteredClient() {
    RegisteredClient registeredClient = RegisteredClient.withId(new SnowFlake(31).nextId() + "")
      .clientId(CLIENT_ID)
      .clientSecret("{noop}" + CLIENT_SECRET)
      .clientAuthenticationMethod(ClientAuthenticationMethod.CLIENT_SECRET_BASIC)
      .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
      .scope(OidcScopes.OPENID)
      .scope(OidcScopes.PROFILE)
      .build();
    registeredClientRepository
      .save(registeredClient);
  }
}

2.发送请求

1. idea httprequest脚本

### client_secret_basic 请求方式
# state参数可选
# Authorization: Basic Base64(client_id:client_secret)
POST http://{{host}}:{{port}}/oauth2/token?grant_type=client_credentials&client_id={{client_id}}&state={{state}}
Content-Type: application/x-www-form-urlencoded
Authorization: Basic {{client_id}} {{client_secret}}

### 测试例子
POST http://localhost:5001/oauth2/token
Authorization: Basic test_client_secret_basic secret
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&client_id=test_client_secret_basic

2.curl请求方式

curl -i -v  -X POST -u "test_client_secret_basic:secret" -d "grant_type=client_credentials&client_id=test_client_secret_basic" http://localhost:5001/oauth2/token

3. apiPost文档

https://console-docs.apipost.cn/preview/5c835f3c5869ecba/f51728e8bf6cc72a?target_id=8657169f-7a42-4b29-935f-5f99ee0c8153

4.测试案例

https://gitee.com/elsfs/elsfs/blob/master/auth/spring-auth/src/test/java/org/elsfs/auth/client/CLIENT_SECRET_BASIC.java

.认证过程

1.进入OAuth2ClientAuthenticationFilter过滤器
public final class OAuth2ClientAuthenticationFilter extends OncePerRequestFilter {
    @Override
	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
			throws ServletException, IOException {
        /**
        * 判断请求方式是不是 /oauth2/token', POST; /oauth2/introspect', POST;/oauth2/revoke, POST; /oauth2/device_authorization, POST
        * 如果不是直接略过
        */
		if (!this.requestMatcher.matches(request)) {
			filterChain.doFilter(request, response);
			return;
		}

		try {
            /**
            * (1)
            * 到 DelegatingAuthenticationConverter筛选转换器
            * 转化器 一共有4个 对应4种请求方式
            *  JwtClientAssertionAuthenticationConverter
            *  ClientSecretBasicAuthenticationConverter
            *  ClientSecretPostAuthenticationConverter
            *  PublicClientAuthenticationConverter
            * 这里使用的是 ClientSecretBasicAuthenticationConverter 转换得到OAuth2ClientAuthenticationToken
            */
			Authentication authenticationRequest = this.authenticationConverter.convert(request);
			if (authenticationRequest instanceof AbstractAuthenticationToken) {
				((AbstractAuthenticationToken) authenticationRequest).setDetails(
						this.authenticationDetailsSource.buildDetails(request));
			}
			if (authenticationRequest != null) {
                // 验证的客户端id是否符合oauth2规范
				validateClientIdentifier(authenticationRequest);
                /**
                *   (2)
                * 在 ProviderManager 筛选 AuthenticationProvider 然后调用筛选的AuthenticationProvider authenticate方法返回Authentication对象
                * 该处筛选 的是 ClientSecretAuthenticationProvider
                */
				Authentication authenticationResult = this.authenticationManager.authenticate(authenticationRequest);
				// 发布成功事件
                this.authenticationSuccessHandler.onAuthenticationSuccess(request, response, authenticationResult);
			}
			filterChain.doFilter(request, response);

		} catch (OAuth2AuthenticationException ex) {
			if (this.logger.isTraceEnabled()) {
				this.logger.trace(LogMessage.format("Client authentication failed: %s", ex.getError()), ex);
			}
			this.authenticationFailureHandler.onAuthenticationFailure(request, response, ex);
		}
	}

}

(2)

public final class ClientSecretBasicAuthenticationConverter implements AuthenticationConverter {

	@Nullable
	@Override
	public Authentication convert(HttpServletRequest request) {
        // 获取 Authorization
		String header = request.getHeader(HttpHeaders.AUTHORIZATION);
		if (header == null) {
			return null;
		}
        // b把Basic 和token分离出来
		String[] parts = header.split("\\s");
		if (!parts[0].equalsIgnoreCase("Basic")) {
			return null;
		}

		if (parts.length != 2) {
			throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_REQUEST);
		}

		byte[] decodedCredentials;
		try {
			decodedCredentials = Base64.getDecoder().decode(
					parts[1].getBytes(StandardCharsets.UTF_8));
		} catch (IllegalArgumentException ex) {
			throw new OAuth2AuthenticationException(new OAuth2Error(OAuth2ErrorCodes.INVALID_REQUEST), ex);
		}
		String credentialsString = new String(decodedCredentials, StandardCharsets.UTF_8);
		String[] credentials = credentialsString.split(":", 2);
		if (credentials.length != 2 ||
				!StringUtils.hasText(credentials[0]) ||
				!StringUtils.hasText(credentials[1])) {
			throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_REQUEST);
		}

        // 获取 clientID和clientSecret
		String clientID;
		String clientSecret;
		try {
			clientID = URLDecoder.decode(credentials[0], StandardCharsets.UTF_8.name());
			clientSecret = URLDecoder.decode(credentials[1], StandardCharsets.UTF_8.name());
		} catch (Exception ex) {
			throw new OAuth2AuthenticationException(new OAuth2Error(OAuth2ErrorCodes.INVALID_REQUEST), ex);
		}

		return new OAuth2ClientAuthenticationToken(clientID, ClientAuthenticationMethod.CLIENT_SECRET_BASIC, clientSecret,
				OAuth2EndpointUtils.getParametersIfMatchesAuthorizationCodeGrantRequest(request));
	}

}

(2)

public final class ClientSecretAuthenticationProvider implements AuthenticationProvider {

	@Override
	public Authentication authenticate(Authentication authentication) throws AuthenticationException {
		OAuth2ClientAuthenticationToken clientAuthentication =
				(OAuth2ClientAuthenticationToken) authentication;
            // 该 AuthenticationProvider 支持 client_secret_basic 和 client_secret_post
            // 他们的区别就是请求参数是 body (client_secret_post)和 query(client_secret_basic)
		if (!ClientAuthenticationMethod.CLIENT_SECRET_BASIC.equals(clientAuthentication.getClientAuthenticationMethod()) &&
				!ClientAuthenticationMethod.CLIENT_SECRET_POST.equals(clientAuthentication.getClientAuthenticationMethod())) {
			return null;
		}

		String clientId = clientAuthentication.getPrincipal().toString();
        // 查询 RegisteredClient
		RegisteredClient registeredClient = this.registeredClientRepository.findByClientId(clientId);
		if (registeredClient == null) {
			throwInvalidClient(OAuth2ParameterNames.CLIENT_ID);
		}

		if (this.logger.isTraceEnabled()) {
			this.logger.trace("Retrieved registered client");
		}
        // 判断RegisteredClient是否支持该请求方式
		if (!registeredClient.getClientAuthenticationMethods().contains(
				clientAuthentication.getClientAuthenticationMethod())) {
			throwInvalidClient("authentication_method");
		}

		if (clientAuthentication.getCredentials() == null) {
			throwInvalidClient("credentials");
		}
        // 验证客户端密码
		String clientSecret = clientAuthentication.getCredentials().toString();
		if (!this.passwordEncoder.matches(clientSecret, registeredClient.getClientSecret())) {
			throwInvalidClient(OAuth2ParameterNames.CLIENT_SECRET);
		}
        // 判断密码是否过期
		if (registeredClient.getClientSecretExpiresAt() != null &&
				Instant.now().isAfter(registeredClient.getClientSecretExpiresAt())) {
			throwInvalidClient("client_secret_expires_at");
		}
        // 更新为安全密码
		if (this.passwordEncoder.upgradeEncoding(registeredClient.getClientSecret())) {
			registeredClient = RegisteredClient.from(registeredClient)
					.clientSecret(this.passwordEncoder.encode(clientSecret))
					.build();
			this.registeredClientRepository.save(registeredClient);
		}

		if (this.logger.isTraceEnabled()) {
			this.logger.trace("Validated client authentication parameters");
		}
        // 验证 code_verifier
		// Validate the "code_verifier" parameter for the confidential client, if available
		this.codeVerifierAuthenticator.authenticateIfAvailable(clientAuthentication, registeredClient);

		if (this.logger.isTraceEnabled()) {
			this.logger.trace("Authenticated client secret");
		}

		return new OAuth2ClientAuthenticationToken(registeredClient,
				clientAuthentication.getClientAuthenticationMethod(), clientAuthentication.getCredentials());
	}
}
生成token
public final class OAuth2TokenEndpointFilter extends OncePerRequestFilter {

	@Override
	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
			throws ServletException, IOException {
        // 判断是否 Post /oauth2/token
		if (!this.tokenEndpointMatcher.matches(request)) {
			filterChain.doFilter(request, response);
			return;
		}

		try {
            // client_credentials
			String[] grantTypes = request.getParameterValues(OAuth2ParameterNames.GRANT_TYPE);
			if (grantTypes == null || grantTypes.length != 1) {
				throwError(OAuth2ErrorCodes.INVALID_REQUEST, OAuth2ParameterNames.GRANT_TYPE);
			}
            /**
            *(1)
            * 通过 DelegatingAuthenticationConverter 获取 OAuth2ClientCredentialsAuthenticationConverter 然后获取Authentication
            * 这里的转化器一共有4个
            * 	 OAuth2AuthorizationCodeAuthenticationConverter
            * 	 OAuth2RefreshTokenAuthenticationConverter
            * 	 OAuth2ClientCredentialsAuthenticationConverter
            * 	 OAuth2DeviceCodeAuthenticationConverter
            */
			Authentication authorizationGrantAuthentication = this.authenticationConverter.convert(request);
			if (authorizationGrantAuthentication == null) {
				throwError(OAuth2ErrorCodes.UNSUPPORTED_GRANT_TYPE, OAuth2ParameterNames.GRANT_TYPE);
			}
			if (authorizationGrantAuthentication instanceof AbstractAuthenticationToken) {
				((AbstractAuthenticationToken) authorizationGrantAuthentication)
						.setDetails(this.authenticationDetailsSource.buildDetails(request));
			}
            /**
            * (2)
            *  通过 ProviderManager 获取 OAuth2ClientCredentialsAuthenticationProvider 然后通过
            *   该AuthenticationProvider获取OAuth2AccessTokenAuthenticationToken 至此完成认证返回token
            *
            */
			OAuth2AccessTokenAuthenticationToken accessTokenAuthentication =
					(OAuth2AccessTokenAuthenticationToken) this.authenticationManager.authenticate(authorizationGrantAuthentication);
			this.authenticationSuccessHandler.onAuthenticationSuccess(request, response, accessTokenAuthentication);
		} catch (OAuth2AuthenticationException ex) {
			SecurityContextHolder.clearContext();
			if (this.logger.isTraceEnabled()) {
				this.logger.trace(LogMessage.format("Token request failed: %s", ex.getError()), ex);
			}
			this.authenticationFailureHandler.onAuthenticationFailure(request, response, ex);
		}
	}
}

(2)

public final class OAuth2ClientCredentialsAuthenticationConverter implements AuthenticationConverter {

	@Nullable
	@Override
	public Authentication convert(HttpServletRequest request) {
		// grant_type = client_credentials 处理
		String grantType = request.getParameter(OAuth2ParameterNames.GRANT_TYPE);
		if (!AuthorizationGrantType.CLIENT_CREDENTIALS.getValue().equals(grantType)) {
			return null;
		}
        // 获取 OAuth2ClientAuthenticationToken
		Authentication clientPrincipal = SecurityContextHolder.getContext().getAuthentication();
        // 获取grant_type client_id state state是可选的
		MultiValueMap<String, String> parameters = OAuth2EndpointUtils.getParameters(request);

		// scope (OPTIONAL)
        // 验证 scope
		String scope = parameters.getFirst(OAuth2ParameterNames.SCOPE);
		if (StringUtils.hasText(scope) &&
				parameters.get(OAuth2ParameterNames.SCOPE).size() != 1) {
			OAuth2EndpointUtils.throwError(
					OAuth2ErrorCodes.INVALID_REQUEST,
					OAuth2ParameterNames.SCOPE,
					OAuth2EndpointUtils.ACCESS_TOKEN_REQUEST_ERROR_URI);
		}
		Set<String> requestedScopes = null;
		if (StringUtils.hasText(scope)) {
			requestedScopes = new HashSet<>(
					Arrays.asList(StringUtils.delimitedListToStringArray(scope, " ")));
		}

		Map<String, Object> additionalParameters = new HashMap<>();
		parameters.forEach((key, value) -> {
			if (!key.equals(OAuth2ParameterNames.GRANT_TYPE) &&
					!key.equals(OAuth2ParameterNames.SCOPE)) {
				additionalParameters.put(key, value.get(0));
			}
		});

		return new OAuth2ClientCredentialsAuthenticationToken(
				clientPrincipal, requestedScopes, additionalParameters);
	}
}

(2)

public final class OAuth2ClientCredentialsAuthenticationProvider implements AuthenticationProvider {

	@Override
	public Authentication authenticate(Authentication authentication) throws AuthenticationException {
		OAuth2ClientCredentialsAuthenticationToken clientCredentialsAuthentication =
				(OAuth2ClientCredentialsAuthenticationToken) authentication;

		OAuth2ClientAuthenticationToken clientPrincipal =
				getAuthenticatedClientElseThrowInvalidClient(clientCredentialsAuthentication);
		RegisteredClient registeredClient = clientPrincipal.getRegisteredClient();

		if (this.logger.isTraceEnabled()) {
			this.logger.trace("Retrieved registered client");
		}
        // 再一次验证  该客户端AuthorizationGrantType 是否支持 client_credentials
		if (!registeredClient.getAuthorizationGrantTypes().contains(AuthorizationGrantType.CLIENT_CREDENTIALS)) {
			throw new OAuth2AuthenticationException(OAuth2ErrorCodes.UNAUTHORIZED_CLIENT);
		}
        // 获取请求的 scope
		Set<String> authorizedScopes = Collections.emptySet();
		if (!CollectionUtils.isEmpty(clientCredentialsAuthentication.getScopes())) {
			for (String requestedScope : clientCredentialsAuthentication.getScopes()) {
				if (!registeredClient.getScopes().contains(requestedScope)) {
					throw new OAuth2AuthenticationException(OAuth2ErrorCodes.INVALID_SCOPE);
				}
			}
			authorizedScopes = new LinkedHashSet<>(clientCredentialsAuthentication.getScopes());
		}

		if (this.logger.isTraceEnabled()) {
			this.logger.trace("Validated token request parameters");
		}
        // 构建 OAuth2令牌上下文
		// @formatter:off
		OAuth2TokenContext tokenContext = DefaultOAuth2TokenContext.builder()
				.registeredClient(registeredClient)
				.principal(clientPrincipal)
				.authorizationServerContext(AuthorizationServerContextHolder.getContext())
				.authorizedScopes(authorizedScopes)
				.tokenType(OAuth2TokenType.ACCESS_TOKEN)
				.authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
				.authorizationGrant(clientCredentialsAuthentication)
				.build();
		// @formatter:on
        /**
        * 生成 oauth2Token
        * (3)
        * 默认 是RegisteredClient .tokenSettings(TokenSettings.builder().accessTokenFormat(OAuth2TokenFormat.SELF_CONTAINED).build())
        * 通过 DelegatingOAuth2TokenGenerator 获取JwtGenerator生成token 透明的token 他就是token
        * (4)
        *       如果RegisteredClient .tokenSettings(TokenSettings.builder().accessTokenFormat(OAuth2TokenFormat.REFERENCE).build())
        * 通过 DelegatingOAuth2TokenGenerator 获取 OAuth2AccessTokenGenerator  生成token 不透明的token 他就是一串96长度的字符串
        */
		OAuth2Token generatedAccessToken = this.tokenGenerator.generate(tokenContext);
		if (generatedAccessToken == null) {
			OAuth2Error error = new OAuth2Error(OAuth2ErrorCodes.SERVER_ERROR,
					"The token generator failed to generate the access token.", ERROR_URI);
			throw new OAuth2AuthenticationException(error);
		}

		if (this.logger.isTraceEnabled()) {
			this.logger.trace("Generated access token");
		}

		OAuth2AccessToken accessToken = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER,
				generatedAccessToken.getTokenValue(), generatedAccessToken.getIssuedAt(),
				generatedAccessToken.getExpiresAt(), tokenContext.getAuthorizedScopes());

		// @formatter:off
		OAuth2Authorization.Builder authorizationBuilder = OAuth2Authorization.withRegisteredClient(registeredClient)
				.principalName(clientPrincipal.getName())
				.authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
				.authorizedScopes(authorizedScopes);
		// @formatter:on
		if (generatedAccessToken instanceof ClaimAccessor) {
			authorizationBuilder.token(accessToken, (metadata) ->
					metadata.put(OAuth2Authorization.Token.CLAIMS_METADATA_NAME, ((ClaimAccessor) generatedAccessToken).getClaims()));
		} else {
			authorizationBuilder.accessToken(accessToken);
		}

		OAuth2Authorization authorization = authorizationBuilder.build();
        // 保存token信息
		this.authorizationService.save(authorization);

		if (this.logger.isTraceEnabled()) {
			this.logger.trace("Saved authorization");
			// This log is kept separate for consistency with other providers
			this.logger.trace("Authenticated token request");
		}

		return new OAuth2AccessTokenAuthenticationToken(registeredClient, clientPrincipal, accessToken);
	}

}

(3)

public final class JwtGenerator implements OAuth2TokenGenerator<Jwt> {
    @Nullable
	@Override
	public Jwt generate(OAuth2TokenContext context) {
        //不支持 access_token 和id_token
		if (context.getTokenType() == null ||
				(!OAuth2TokenType.ACCESS_TOKEN.equals(context.getTokenType()) &&
						!OidcParameterNames.ID_TOKEN.equals(context.getTokenType().getValue()))) {
			return null;
		}
        //  支持 self-contained 透明的token 也就是 jwt token
		if (OAuth2TokenType.ACCESS_TOKEN.equals(context.getTokenType()) &&
				!OAuth2TokenFormat.SELF_CONTAINED.equals(context.getRegisteredClient().getTokenSettings().getAccessTokenFormat())) {
			return null;
		}

		String issuer = null;
		if (context.getAuthorizationServerContext() != null) {
			issuer = context.getAuthorizationServerContext().getIssuer();
		}
		RegisteredClient registeredClient = context.getRegisteredClient();

		Instant issuedAt = Instant.now();
		Instant expiresAt;
		JwsAlgorithm jwsAlgorithm = SignatureAlgorithm.RS256;
		if (OidcParameterNames.ID_TOKEN.equals(context.getTokenType().getValue())) {
			// TODO Allow configuration for ID Token time-to-live
			expiresAt = issuedAt.plus(30, ChronoUnit.MINUTES);
			if (registeredClient.getTokenSettings().getIdTokenSignatureAlgorithm() != null) {
				jwsAlgorithm = registeredClient.getTokenSettings().getIdTokenSignatureAlgorithm();
			}
		} else {
			expiresAt = issuedAt.plus(registeredClient.getTokenSettings().getAccessTokenTimeToLive());
		}

		// @formatter:off
		JwtClaimsSet.Builder claimsBuilder = JwtClaimsSet.builder();
		if (StringUtils.hasText(issuer)) {
			claimsBuilder.issuer(issuer);
		}
		claimsBuilder
				.subject(context.getPrincipal().getName())
				.audience(Collections.singletonList(registeredClient.getClientId()))
				.issuedAt(issuedAt)
				.expiresAt(expiresAt);
		if (OAuth2TokenType.ACCESS_TOKEN.equals(context.getTokenType())) {
			claimsBuilder.notBefore(issuedAt);
			if (!CollectionUtils.isEmpty(context.getAuthorizedScopes())) {
				claimsBuilder.claim(OAuth2ParameterNames.SCOPE, context.getAuthorizedScopes());
			}
		} else if (OidcParameterNames.ID_TOKEN.equals(context.getTokenType().getValue())) {
			claimsBuilder.claim(IdTokenClaimNames.AZP, registeredClient.getClientId());
			if (AuthorizationGrantType.AUTHORIZATION_CODE.equals(context.getAuthorizationGrantType())) {
				OAuth2AuthorizationRequest authorizationRequest = context.getAuthorization().getAttribute(
						OAuth2AuthorizationRequest.class.getName());
				String nonce = (String) authorizationRequest.getAdditionalParameters().get(OidcParameterNames.NONCE);
				if (StringUtils.hasText(nonce)) {
					claimsBuilder.claim(IdTokenClaimNames.NONCE, nonce);
				}
			}
			SessionInformation sessionInformation = context.get(SessionInformation.class);
			if (sessionInformation != null) {
				claimsBuilder.claim("sid", sessionInformation.getSessionId());
				claimsBuilder.claim(IdTokenClaimNames.AUTH_TIME, sessionInformation.getLastRequest());
			}
		}
		// @formatter:on

		JwsHeader.Builder jwsHeaderBuilder = JwsHeader.with(jwsAlgorithm);

		if (this.jwtCustomizer != null) {
			// @formatter:off
			JwtEncodingContext.Builder jwtContextBuilder = JwtEncodingContext.with(jwsHeaderBuilder, claimsBuilder)
					.registeredClient(context.getRegisteredClient())
					.principal(context.getPrincipal())
					.authorizationServerContext(context.getAuthorizationServerContext())
					.authorizedScopes(context.getAuthorizedScopes())
					.tokenType(context.getTokenType())
					.authorizationGrantType(context.getAuthorizationGrantType());
			if (context.getAuthorization() != null) {
				jwtContextBuilder.authorization(context.getAuthorization());
			}
			if (context.getAuthorizationGrant() != null) {
				jwtContextBuilder.authorizationGrant(context.getAuthorizationGrant());
			}
			if (OidcParameterNames.ID_TOKEN.equals(context.getTokenType().getValue())) {
				SessionInformation sessionInformation = context.get(SessionInformation.class);
				if (sessionInformation != null) {
					jwtContextBuilder.put(SessionInformation.class, sessionInformation);
				}
			}
			// @formatter:on

			JwtEncodingContext jwtContext = jwtContextBuilder.build();
			this.jwtCustomizer.customize(jwtContext);
		}

		JwsHeader jwsHeader = jwsHeaderBuilder.build();
		JwtClaimsSet claims = claimsBuilder.build();

		Jwt jwt = this.jwtEncoder.encode(JwtEncoderParameters.from(jwsHeader, claims));

		return jwt;
	}
}

(4)

public final class OAuth2AccessTokenGenerator implements OAuth2TokenGenerator<OAuth2AccessToken> {
	@Nullable
	@Override
	public OAuth2AccessToken generate(OAuth2TokenContext context) {
		if (!OAuth2TokenType.ACCESS_TOKEN.equals(context.getTokenType()) ||
				!OAuth2TokenFormat.REFERENCE.equals(context.getRegisteredClient().getTokenSettings().getAccessTokenFormat())) {
			return null;
		}

		String issuer = null;
		if (context.getAuthorizationServerContext() != null) {
			issuer = context.getAuthorizationServerContext().getIssuer();
		}
		RegisteredClient registeredClient = context.getRegisteredClient();

		Instant issuedAt = Instant.now();
		Instant expiresAt = issuedAt.plus(registeredClient.getTokenSettings().getAccessTokenTimeToLive());

		// @formatter:off
		OAuth2TokenClaimsSet.Builder claimsBuilder = OAuth2TokenClaimsSet.builder();
		if (StringUtils.hasText(issuer)) {
			claimsBuilder.issuer(issuer);
		}
		claimsBuilder
				.subject(context.getPrincipal().getName())
				.audience(Collections.singletonList(registeredClient.getClientId()))
				.issuedAt(issuedAt)
				.expiresAt(expiresAt)
				.notBefore(issuedAt)
				.id(UUID.randomUUID().toString());
		if (!CollectionUtils.isEmpty(context.getAuthorizedScopes())) {
			claimsBuilder.claim(OAuth2ParameterNames.SCOPE, context.getAuthorizedScopes());
		}
		// @formatter:on

		if (this.accessTokenCustomizer != null) {
			// @formatter:off
			OAuth2TokenClaimsContext.Builder accessTokenContextBuilder = OAuth2TokenClaimsContext.with(claimsBuilder)
					.registeredClient(context.getRegisteredClient())
					.principal(context.getPrincipal())
					.authorizationServerContext(context.getAuthorizationServerContext())
					.authorizedScopes(context.getAuthorizedScopes())
					.tokenType(context.getTokenType())
					.authorizationGrantType(context.getAuthorizationGrantType());
			if (context.getAuthorization() != null) {
				accessTokenContextBuilder.authorization(context.getAuthorization());
			}
			if (context.getAuthorizationGrant() != null) {
				accessTokenContextBuilder.authorizationGrant(context.getAuthorizationGrant());
			}
			// @formatter:on

			OAuth2TokenClaimsContext accessTokenContext = accessTokenContextBuilder.build();
			this.accessTokenCustomizer.customize(accessTokenContext);
		}

		OAuth2TokenClaimsSet accessTokenClaimsSet = claimsBuilder.build();

		OAuth2AccessToken accessToken = new OAuth2AccessTokenClaims(OAuth2AccessToken.TokenType.BEARER,
				this.accessTokenGenerator.generateKey(), accessTokenClaimsSet.getIssuedAt(), accessTokenClaimsSet.getExpiresAt(),
				context.getAuthorizedScopes(), accessTokenClaimsSet.getClaims());

		return accessToken;
	}

}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值