mirror of
				https://github.com/spring-projects/spring-security.git
				synced 2025-10-31 06:38:42 +00:00 
			
		
		
		
	Associate Refresh Token to OAuth2AuthorizedClient
Fixes gh-5416
This commit is contained in:
		
							parent
							
								
									1137f3b46d
								
							
						
					
					
						commit
						02d29887fb
					
				| @ -1,5 +1,5 @@ | |||||||
| /* | /* | ||||||
|  * Copyright 2002-2017 the original author or authors. |  * Copyright 2002-2018 the original author or authors. | ||||||
|  * |  * | ||||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); |  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  * you may not use this file except in compliance with the License. |  * you may not use this file except in compliance with the License. | ||||||
| @ -15,8 +15,10 @@ | |||||||
|  */ |  */ | ||||||
| package org.springframework.security.oauth2.client; | package org.springframework.security.oauth2.client; | ||||||
| 
 | 
 | ||||||
|  | import org.springframework.lang.Nullable; | ||||||
| import org.springframework.security.oauth2.client.registration.ClientRegistration; | import org.springframework.security.oauth2.client.registration.ClientRegistration; | ||||||
| import org.springframework.security.oauth2.core.OAuth2AccessToken; | import org.springframework.security.oauth2.core.OAuth2AccessToken; | ||||||
|  | import org.springframework.security.oauth2.core.OAuth2RefreshToken; | ||||||
| import org.springframework.util.Assert; | import org.springframework.util.Assert; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
| @ -33,11 +35,13 @@ import org.springframework.util.Assert; | |||||||
|  * @since 5.0 |  * @since 5.0 | ||||||
|  * @see ClientRegistration |  * @see ClientRegistration | ||||||
|  * @see OAuth2AccessToken |  * @see OAuth2AccessToken | ||||||
|  |  * @see OAuth2RefreshToken | ||||||
|  */ |  */ | ||||||
| public class OAuth2AuthorizedClient { | public class OAuth2AuthorizedClient { | ||||||
| 	private final ClientRegistration clientRegistration; | 	private final ClientRegistration clientRegistration; | ||||||
| 	private final String principalName; | 	private final String principalName; | ||||||
| 	private final OAuth2AccessToken accessToken; | 	private final OAuth2AccessToken accessToken; | ||||||
|  | 	private final OAuth2RefreshToken refreshToken; | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Constructs an {@code OAuth2AuthorizedClient} using the provided parameters. | 	 * Constructs an {@code OAuth2AuthorizedClient} using the provided parameters. | ||||||
| @ -47,12 +51,26 @@ public class OAuth2AuthorizedClient { | |||||||
| 	 * @param accessToken the access token credential granted | 	 * @param accessToken the access token credential granted | ||||||
| 	 */ | 	 */ | ||||||
| 	public OAuth2AuthorizedClient(ClientRegistration clientRegistration, String principalName, OAuth2AccessToken accessToken) { | 	public OAuth2AuthorizedClient(ClientRegistration clientRegistration, String principalName, OAuth2AccessToken accessToken) { | ||||||
|  | 		this(clientRegistration, principalName, accessToken, null); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Constructs an {@code OAuth2AuthorizedClient} using the provided parameters. | ||||||
|  | 	 * | ||||||
|  | 	 * @param clientRegistration the authorized client's registration | ||||||
|  | 	 * @param principalName the name of the End-User {@code Principal} (Resource Owner) | ||||||
|  | 	 * @param accessToken the access token credential granted | ||||||
|  | 	 * @param refreshToken the refresh token credential granted | ||||||
|  | 	 */ | ||||||
|  | 	public OAuth2AuthorizedClient(ClientRegistration clientRegistration, String principalName, | ||||||
|  | 									OAuth2AccessToken accessToken, @Nullable OAuth2RefreshToken refreshToken) { | ||||||
| 		Assert.notNull(clientRegistration, "clientRegistration cannot be null"); | 		Assert.notNull(clientRegistration, "clientRegistration cannot be null"); | ||||||
| 		Assert.hasText(principalName, "principalName cannot be empty"); | 		Assert.hasText(principalName, "principalName cannot be empty"); | ||||||
| 		Assert.notNull(accessToken, "accessToken cannot be null"); | 		Assert.notNull(accessToken, "accessToken cannot be null"); | ||||||
| 		this.clientRegistration = clientRegistration; | 		this.clientRegistration = clientRegistration; | ||||||
| 		this.principalName = principalName; | 		this.principalName = principalName; | ||||||
| 		this.accessToken = accessToken; | 		this.accessToken = accessToken; | ||||||
|  | 		this.refreshToken = refreshToken; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| @ -81,4 +99,14 @@ public class OAuth2AuthorizedClient { | |||||||
| 	public OAuth2AccessToken getAccessToken() { | 	public OAuth2AccessToken getAccessToken() { | ||||||
| 		return this.accessToken; | 		return this.accessToken; | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Returns the {@link OAuth2RefreshToken refresh token} credential granted. | ||||||
|  | 	 * | ||||||
|  | 	 * @since 5.1 | ||||||
|  | 	 * @return the {@link OAuth2RefreshToken} | ||||||
|  | 	 */ | ||||||
|  | 	public @Nullable OAuth2RefreshToken getRefreshToken() { | ||||||
|  | 		return this.refreshToken; | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  | |||||||
| @ -20,7 +20,6 @@ import org.springframework.security.core.Authentication; | |||||||
| import org.springframework.security.core.AuthenticationException; | import org.springframework.security.core.AuthenticationException; | ||||||
| import org.springframework.security.oauth2.client.endpoint.OAuth2AccessTokenResponseClient; | import org.springframework.security.oauth2.client.endpoint.OAuth2AccessTokenResponseClient; | ||||||
| import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeGrantRequest; | import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeGrantRequest; | ||||||
| import org.springframework.security.oauth2.core.OAuth2AccessToken; |  | ||||||
| import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; | import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; | ||||||
| import org.springframework.util.Assert; | import org.springframework.util.Assert; | ||||||
| 
 | 
 | ||||||
| @ -69,13 +68,12 @@ public class OAuth2AuthorizationCodeAuthenticationProvider implements Authentica | |||||||
| 					authorizationCodeAuthentication.getClientRegistration(), | 					authorizationCodeAuthentication.getClientRegistration(), | ||||||
| 					authorizationCodeAuthentication.getAuthorizationExchange())); | 					authorizationCodeAuthentication.getAuthorizationExchange())); | ||||||
| 
 | 
 | ||||||
| 		OAuth2AccessToken accessToken = accessTokenResponse.getAccessToken(); |  | ||||||
| 
 |  | ||||||
| 		OAuth2AuthorizationCodeAuthenticationToken authenticationResult = | 		OAuth2AuthorizationCodeAuthenticationToken authenticationResult = | ||||||
| 			new OAuth2AuthorizationCodeAuthenticationToken( | 			new OAuth2AuthorizationCodeAuthenticationToken( | ||||||
| 				authorizationCodeAuthentication.getClientRegistration(), | 				authorizationCodeAuthentication.getClientRegistration(), | ||||||
| 				authorizationCodeAuthentication.getAuthorizationExchange(), | 				authorizationCodeAuthentication.getAuthorizationExchange(), | ||||||
| 				accessToken); | 				accessTokenResponse.getAccessToken(), | ||||||
|  | 				accessTokenResponse.getRefreshToken()); | ||||||
| 		authenticationResult.setDetails(authorizationCodeAuthentication.getDetails()); | 		authenticationResult.setDetails(authorizationCodeAuthentication.getDetails()); | ||||||
| 
 | 
 | ||||||
| 		return authenticationResult; | 		return authenticationResult; | ||||||
|  | |||||||
| @ -15,10 +15,12 @@ | |||||||
|  */ |  */ | ||||||
| package org.springframework.security.oauth2.client.authentication; | package org.springframework.security.oauth2.client.authentication; | ||||||
| 
 | 
 | ||||||
|  | import org.springframework.lang.Nullable; | ||||||
| import org.springframework.security.authentication.AbstractAuthenticationToken; | import org.springframework.security.authentication.AbstractAuthenticationToken; | ||||||
| import org.springframework.security.core.SpringSecurityCoreVersion; | import org.springframework.security.core.SpringSecurityCoreVersion; | ||||||
| import org.springframework.security.oauth2.client.registration.ClientRegistration; | import org.springframework.security.oauth2.client.registration.ClientRegistration; | ||||||
| import org.springframework.security.oauth2.core.OAuth2AccessToken; | import org.springframework.security.oauth2.core.OAuth2AccessToken; | ||||||
|  | import org.springframework.security.oauth2.core.OAuth2RefreshToken; | ||||||
| import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationExchange; | import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationExchange; | ||||||
| import org.springframework.util.Assert; | import org.springframework.util.Assert; | ||||||
| 
 | 
 | ||||||
| @ -40,6 +42,7 @@ public class OAuth2AuthorizationCodeAuthenticationToken extends AbstractAuthenti | |||||||
| 	private ClientRegistration clientRegistration; | 	private ClientRegistration clientRegistration; | ||||||
| 	private OAuth2AuthorizationExchange authorizationExchange; | 	private OAuth2AuthorizationExchange authorizationExchange; | ||||||
| 	private OAuth2AccessToken accessToken; | 	private OAuth2AccessToken accessToken; | ||||||
|  | 	private OAuth2RefreshToken refreshToken; | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * This constructor should be used when the Authorization Request/Response is complete. | 	 * This constructor should be used when the Authorization Request/Response is complete. | ||||||
| @ -67,9 +70,26 @@ public class OAuth2AuthorizationCodeAuthenticationToken extends AbstractAuthenti | |||||||
| 	public OAuth2AuthorizationCodeAuthenticationToken(ClientRegistration clientRegistration, | 	public OAuth2AuthorizationCodeAuthenticationToken(ClientRegistration clientRegistration, | ||||||
| 														OAuth2AuthorizationExchange authorizationExchange, | 														OAuth2AuthorizationExchange authorizationExchange, | ||||||
| 														OAuth2AccessToken accessToken) { | 														OAuth2AccessToken accessToken) { | ||||||
|  | 		this(clientRegistration, authorizationExchange, accessToken, null); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * This constructor should be used when the Access Token Request/Response is complete, | ||||||
|  | 	 * which indicates that the Authorization Code Grant flow has fully completed. | ||||||
|  | 	 * | ||||||
|  | 	 * @param clientRegistration the client registration | ||||||
|  | 	 * @param authorizationExchange the authorization exchange | ||||||
|  | 	 * @param accessToken the access token credential | ||||||
|  | 	 * @param refreshToken the refresh token credential | ||||||
|  | 	 */ | ||||||
|  | 	public OAuth2AuthorizationCodeAuthenticationToken(ClientRegistration clientRegistration, | ||||||
|  | 														OAuth2AuthorizationExchange authorizationExchange, | ||||||
|  | 														OAuth2AccessToken accessToken, | ||||||
|  | 														@Nullable OAuth2RefreshToken refreshToken) { | ||||||
| 		this(clientRegistration, authorizationExchange); | 		this(clientRegistration, authorizationExchange); | ||||||
| 		Assert.notNull(accessToken, "accessToken cannot be null"); | 		Assert.notNull(accessToken, "accessToken cannot be null"); | ||||||
| 		this.accessToken = accessToken; | 		this.accessToken = accessToken; | ||||||
|  | 		this.refreshToken = refreshToken; | ||||||
| 		this.setAuthenticated(true); | 		this.setAuthenticated(true); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| @ -111,4 +131,13 @@ public class OAuth2AuthorizationCodeAuthenticationToken extends AbstractAuthenti | |||||||
| 	public OAuth2AccessToken getAccessToken() { | 	public OAuth2AccessToken getAccessToken() { | ||||||
| 		return this.accessToken; | 		return this.accessToken; | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Returns the {@link OAuth2RefreshToken refresh token}. | ||||||
|  | 	 * | ||||||
|  | 	 * @return the {@link OAuth2RefreshToken} | ||||||
|  | 	 */ | ||||||
|  | 	public @Nullable OAuth2RefreshToken getRefreshToken() { | ||||||
|  | 		return this.refreshToken; | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| /* | /* | ||||||
|  * Copyright 2002-2017 the original author or authors. |  * Copyright 2002-2018 the original author or authors. | ||||||
|  * |  * | ||||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); |  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  * you may not use this file except in compliance with the License. |  * you may not use this file except in compliance with the License. | ||||||
| @ -113,7 +113,8 @@ public class OAuth2LoginAuthenticationProvider implements AuthenticationProvider | |||||||
| 			authorizationCodeAuthentication.getAuthorizationExchange(), | 			authorizationCodeAuthentication.getAuthorizationExchange(), | ||||||
| 			oauth2User, | 			oauth2User, | ||||||
| 			mappedAuthorities, | 			mappedAuthorities, | ||||||
| 			accessToken); | 			accessToken, | ||||||
|  | 			accessTokenResponse.getRefreshToken()); | ||||||
| 		authenticationResult.setDetails(authorizationCodeAuthentication.getDetails()); | 		authenticationResult.setDetails(authorizationCodeAuthentication.getDetails()); | ||||||
| 
 | 
 | ||||||
| 		return authenticationResult; | 		return authenticationResult; | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| /* | /* | ||||||
|  * Copyright 2002-2017 the original author or authors. |  * Copyright 2002-2018 the original author or authors. | ||||||
|  * |  * | ||||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); |  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  * you may not use this file except in compliance with the License. |  * you may not use this file except in compliance with the License. | ||||||
| @ -15,11 +15,13 @@ | |||||||
|  */ |  */ | ||||||
| package org.springframework.security.oauth2.client.authentication; | package org.springframework.security.oauth2.client.authentication; | ||||||
| 
 | 
 | ||||||
|  | import org.springframework.lang.Nullable; | ||||||
| import org.springframework.security.authentication.AbstractAuthenticationToken; | import org.springframework.security.authentication.AbstractAuthenticationToken; | ||||||
| import org.springframework.security.core.GrantedAuthority; | import org.springframework.security.core.GrantedAuthority; | ||||||
| import org.springframework.security.core.SpringSecurityCoreVersion; | import org.springframework.security.core.SpringSecurityCoreVersion; | ||||||
| import org.springframework.security.oauth2.client.registration.ClientRegistration; | import org.springframework.security.oauth2.client.registration.ClientRegistration; | ||||||
| import org.springframework.security.oauth2.core.OAuth2AccessToken; | import org.springframework.security.oauth2.core.OAuth2AccessToken; | ||||||
|  | import org.springframework.security.oauth2.core.OAuth2RefreshToken; | ||||||
| import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationExchange; | import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationExchange; | ||||||
| import org.springframework.security.oauth2.core.user.OAuth2User; | import org.springframework.security.oauth2.core.user.OAuth2User; | ||||||
| import org.springframework.util.Assert; | import org.springframework.util.Assert; | ||||||
| @ -46,6 +48,7 @@ public class OAuth2LoginAuthenticationToken extends AbstractAuthenticationToken | |||||||
| 	private ClientRegistration clientRegistration; | 	private ClientRegistration clientRegistration; | ||||||
| 	private OAuth2AuthorizationExchange authorizationExchange; | 	private OAuth2AuthorizationExchange authorizationExchange; | ||||||
| 	private OAuth2AccessToken accessToken; | 	private OAuth2AccessToken accessToken; | ||||||
|  | 	private OAuth2RefreshToken refreshToken; | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * This constructor should be used when the Authorization Request/Response is complete. | 	 * This constructor should be used when the Authorization Request/Response is complete. | ||||||
| @ -80,6 +83,27 @@ public class OAuth2LoginAuthenticationToken extends AbstractAuthenticationToken | |||||||
| 											OAuth2User principal, | 											OAuth2User principal, | ||||||
| 											Collection<? extends GrantedAuthority> authorities, | 											Collection<? extends GrantedAuthority> authorities, | ||||||
| 											OAuth2AccessToken accessToken) { | 											OAuth2AccessToken accessToken) { | ||||||
|  | 		this(clientRegistration, authorizationExchange, principal, authorities, accessToken, null); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * This constructor should be used when the Access Token Request/Response is complete, | ||||||
|  | 	 * which indicates that the Authorization Code Grant flow has fully completed | ||||||
|  | 	 * and OAuth 2.0 Login has been achieved. | ||||||
|  | 	 * | ||||||
|  | 	 * @param clientRegistration the client registration | ||||||
|  | 	 * @param authorizationExchange the authorization exchange | ||||||
|  | 	 * @param principal the user {@code Principal} registered with the OAuth 2.0 Provider | ||||||
|  | 	 * @param authorities the authorities granted to the user | ||||||
|  | 	 * @param accessToken the access token credential | ||||||
|  | 	 * @param refreshToken the refresh token credential | ||||||
|  | 	 */ | ||||||
|  | 	public OAuth2LoginAuthenticationToken(ClientRegistration clientRegistration, | ||||||
|  | 											OAuth2AuthorizationExchange authorizationExchange, | ||||||
|  | 											OAuth2User principal, | ||||||
|  | 											Collection<? extends GrantedAuthority> authorities, | ||||||
|  | 											OAuth2AccessToken accessToken, | ||||||
|  | 											@Nullable OAuth2RefreshToken refreshToken) { | ||||||
| 		super(authorities); | 		super(authorities); | ||||||
| 		Assert.notNull(clientRegistration, "clientRegistration cannot be null"); | 		Assert.notNull(clientRegistration, "clientRegistration cannot be null"); | ||||||
| 		Assert.notNull(authorizationExchange, "authorizationExchange cannot be null"); | 		Assert.notNull(authorizationExchange, "authorizationExchange cannot be null"); | ||||||
| @ -89,6 +113,7 @@ public class OAuth2LoginAuthenticationToken extends AbstractAuthenticationToken | |||||||
| 		this.authorizationExchange = authorizationExchange; | 		this.authorizationExchange = authorizationExchange; | ||||||
| 		this.principal = principal; | 		this.principal = principal; | ||||||
| 		this.accessToken = accessToken; | 		this.accessToken = accessToken; | ||||||
|  | 		this.refreshToken = refreshToken; | ||||||
| 		this.setAuthenticated(true); | 		this.setAuthenticated(true); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| @ -128,4 +153,14 @@ public class OAuth2LoginAuthenticationToken extends AbstractAuthenticationToken | |||||||
| 	public OAuth2AccessToken getAccessToken() { | 	public OAuth2AccessToken getAccessToken() { | ||||||
| 		return this.accessToken; | 		return this.accessToken; | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Returns the {@link OAuth2RefreshToken refresh token}. | ||||||
|  | 	 * | ||||||
|  | 	 * @since 5.1 | ||||||
|  | 	 * @return the {@link OAuth2RefreshToken} | ||||||
|  | 	 */ | ||||||
|  | 	public @Nullable OAuth2RefreshToken getRefreshToken() { | ||||||
|  | 		return this.refreshToken; | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  | |||||||
| @ -120,11 +120,13 @@ public class OAuth2LoginReactiveAuthenticationManager implements | |||||||
| 							authorizationCodeAuthentication.getAuthorizationExchange(), | 							authorizationCodeAuthentication.getAuthorizationExchange(), | ||||||
| 							oauth2User, | 							oauth2User, | ||||||
| 							mappedAuthorities, | 							mappedAuthorities, | ||||||
| 							accessToken); | 							accessToken, | ||||||
|  | 							accessTokenResponse.getRefreshToken()); | ||||||
| 					OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( | 					OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( | ||||||
| 							authenticationResult.getClientRegistration(), | 							authenticationResult.getClientRegistration(), | ||||||
| 							authenticationResult.getName(), | 							authenticationResult.getName(), | ||||||
| 							authenticationResult.getAccessToken()); | 							authenticationResult.getAccessToken(), | ||||||
|  | 							authenticationResult.getRefreshToken()); | ||||||
| 					OAuth2AuthenticationToken result =  new OAuth2AuthenticationToken( | 					OAuth2AuthenticationToken result =  new OAuth2AuthenticationToken( | ||||||
| 							authenticationResult.getPrincipal(), | 							authenticationResult.getPrincipal(), | ||||||
| 							authenticationResult.getAuthorities(), | 							authenticationResult.getAuthorities(), | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| /* | /* | ||||||
|  * Copyright 2002-2017 the original author or authors. |  * Copyright 2002-2018 the original author or authors. | ||||||
|  * |  * | ||||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); |  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  * you may not use this file except in compliance with the License. |  * you may not use this file except in compliance with the License. | ||||||
| @ -138,12 +138,18 @@ public class NimbusAuthorizationCodeTokenResponseClient implements OAuth2AccessT | |||||||
| 				accessTokenResponse.getTokens().getAccessToken().getScope().toStringList()); | 				accessTokenResponse.getTokens().getAccessToken().getScope().toStringList()); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 		String refreshToken = null; | ||||||
|  | 		if (accessTokenResponse.getTokens().getRefreshToken() != null) { | ||||||
|  | 			refreshToken = accessTokenResponse.getTokens().getRefreshToken().getValue(); | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		Map<String, Object> additionalParameters = new LinkedHashMap<>(accessTokenResponse.getCustomParameters()); | 		Map<String, Object> additionalParameters = new LinkedHashMap<>(accessTokenResponse.getCustomParameters()); | ||||||
| 
 | 
 | ||||||
| 		return OAuth2AccessTokenResponse.withToken(accessToken) | 		return OAuth2AccessTokenResponse.withToken(accessToken) | ||||||
| 			.tokenType(accessTokenType) | 			.tokenType(accessTokenType) | ||||||
| 			.expiresIn(expiresIn) | 			.expiresIn(expiresIn) | ||||||
| 			.scopes(scopes) | 			.scopes(scopes) | ||||||
|  | 			.refreshToken(refreshToken) | ||||||
| 			.additionalParameters(additionalParameters) | 			.additionalParameters(additionalParameters) | ||||||
| 			.build(); | 			.build(); | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -118,6 +118,11 @@ public class NimbusReactiveAuthorizationCodeTokenResponseClient implements React | |||||||
| 									accessToken.getScope().toStringList()); | 									accessToken.getScope().toStringList()); | ||||||
| 						} | 						} | ||||||
| 
 | 
 | ||||||
|  | 						String refreshToken = null; | ||||||
|  | 						if (accessTokenResponse.getTokens().getRefreshToken() != null) { | ||||||
|  | 							refreshToken = accessTokenResponse.getTokens().getRefreshToken().getValue(); | ||||||
|  | 						} | ||||||
|  | 
 | ||||||
| 						Map<String, Object> additionalParameters = new LinkedHashMap<>( | 						Map<String, Object> additionalParameters = new LinkedHashMap<>( | ||||||
| 								accessTokenResponse.getCustomParameters()); | 								accessTokenResponse.getCustomParameters()); | ||||||
| 
 | 
 | ||||||
| @ -125,6 +130,7 @@ public class NimbusReactiveAuthorizationCodeTokenResponseClient implements React | |||||||
| 								.tokenType(accessTokenType) | 								.tokenType(accessTokenType) | ||||||
| 								.expiresIn(expiresIn) | 								.expiresIn(expiresIn) | ||||||
| 								.scopes(scopes) | 								.scopes(scopes) | ||||||
|  | 								.refreshToken(refreshToken) | ||||||
| 								.additionalParameters(additionalParameters) | 								.additionalParameters(additionalParameters) | ||||||
| 								.build(); | 								.build(); | ||||||
| 					}); | 					}); | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| /* | /* | ||||||
|  * Copyright 2002-2017 the original author or authors. |  * Copyright 2002-2018 the original author or authors. | ||||||
|  * |  * | ||||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); |  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  * you may not use this file except in compliance with the License. |  * you may not use this file except in compliance with the License. | ||||||
| @ -27,7 +27,6 @@ import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest; | |||||||
| import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService; | import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService; | ||||||
| import org.springframework.security.oauth2.client.registration.ClientRegistration; | import org.springframework.security.oauth2.client.registration.ClientRegistration; | ||||||
| import org.springframework.security.oauth2.client.userinfo.OAuth2UserService; | import org.springframework.security.oauth2.client.userinfo.OAuth2UserService; | ||||||
| import org.springframework.security.oauth2.core.OAuth2AccessToken; |  | ||||||
| import org.springframework.security.oauth2.core.OAuth2AuthenticationException; | import org.springframework.security.oauth2.core.OAuth2AuthenticationException; | ||||||
| import org.springframework.security.oauth2.core.OAuth2Error; | import org.springframework.security.oauth2.core.OAuth2Error; | ||||||
| import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; | import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; | ||||||
| @ -142,8 +141,6 @@ public class OidcAuthorizationCodeAuthenticationProvider implements Authenticati | |||||||
| 					authorizationCodeAuthentication.getClientRegistration(), | 					authorizationCodeAuthentication.getClientRegistration(), | ||||||
| 					authorizationCodeAuthentication.getAuthorizationExchange())); | 					authorizationCodeAuthentication.getAuthorizationExchange())); | ||||||
| 
 | 
 | ||||||
| 		OAuth2AccessToken accessToken = accessTokenResponse.getAccessToken(); |  | ||||||
| 
 |  | ||||||
| 		ClientRegistration clientRegistration = authorizationCodeAuthentication.getClientRegistration(); | 		ClientRegistration clientRegistration = authorizationCodeAuthentication.getClientRegistration(); | ||||||
| 
 | 
 | ||||||
| 		if (!accessTokenResponse.getAdditionalParameters().containsKey(OidcParameterNames.ID_TOKEN)) { | 		if (!accessTokenResponse.getAdditionalParameters().containsKey(OidcParameterNames.ID_TOKEN)) { | ||||||
| @ -161,7 +158,7 @@ public class OidcAuthorizationCodeAuthenticationProvider implements Authenticati | |||||||
| 		this.validateIdToken(idToken, clientRegistration); | 		this.validateIdToken(idToken, clientRegistration); | ||||||
| 
 | 
 | ||||||
| 		OidcUser oidcUser = this.userService.loadUser( | 		OidcUser oidcUser = this.userService.loadUser( | ||||||
| 			new OidcUserRequest(clientRegistration, accessToken, idToken)); | 			new OidcUserRequest(clientRegistration, accessTokenResponse.getAccessToken(), idToken)); | ||||||
| 
 | 
 | ||||||
| 		Collection<? extends GrantedAuthority> mappedAuthorities = | 		Collection<? extends GrantedAuthority> mappedAuthorities = | ||||||
| 			this.authoritiesMapper.mapAuthorities(oidcUser.getAuthorities()); | 			this.authoritiesMapper.mapAuthorities(oidcUser.getAuthorities()); | ||||||
| @ -171,7 +168,8 @@ public class OidcAuthorizationCodeAuthenticationProvider implements Authenticati | |||||||
| 			authorizationCodeAuthentication.getAuthorizationExchange(), | 			authorizationCodeAuthentication.getAuthorizationExchange(), | ||||||
| 			oidcUser, | 			oidcUser, | ||||||
| 			mappedAuthorities, | 			mappedAuthorities, | ||||||
| 			accessToken); | 			accessTokenResponse.getAccessToken(), | ||||||
|  | 			accessTokenResponse.getRefreshToken()); | ||||||
| 		authenticationResult.setDetails(authorizationCodeAuthentication.getDetails()); | 		authenticationResult.setDetails(authorizationCodeAuthentication.getDetails()); | ||||||
| 
 | 
 | ||||||
| 		return authenticationResult; | 		return authenticationResult; | ||||||
|  | |||||||
| @ -198,7 +198,8 @@ public class OAuth2AuthorizationCodeGrantFilter extends OncePerRequestFilter { | |||||||
| 		OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( | 		OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( | ||||||
| 			authenticationResult.getClientRegistration(), | 			authenticationResult.getClientRegistration(), | ||||||
| 			currentAuthentication.getName(), | 			currentAuthentication.getName(), | ||||||
| 			authenticationResult.getAccessToken()); | 			authenticationResult.getAccessToken(), | ||||||
|  | 			authenticationResult.getRefreshToken()); | ||||||
| 
 | 
 | ||||||
| 		this.authorizedClientService.saveAuthorizedClient(authorizedClient, currentAuthentication); | 		this.authorizedClientService.saveAuthorizedClient(authorizedClient, currentAuthentication); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -173,7 +173,8 @@ public class OAuth2LoginAuthenticationFilter extends AbstractAuthenticationProce | |||||||
| 		OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( | 		OAuth2AuthorizedClient authorizedClient = new OAuth2AuthorizedClient( | ||||||
| 			authenticationResult.getClientRegistration(), | 			authenticationResult.getClientRegistration(), | ||||||
| 			oauth2Authentication.getName(), | 			oauth2Authentication.getName(), | ||||||
| 			authenticationResult.getAccessToken()); | 			authenticationResult.getAccessToken(), | ||||||
|  | 			authenticationResult.getRefreshToken()); | ||||||
| 
 | 
 | ||||||
| 		this.authorizedClientService.saveAuthorizedClient(authorizedClient, oauth2Authentication); | 		this.authorizedClientService.saveAuthorizedClient(authorizedClient, oauth2Authentication); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -27,6 +27,7 @@ import org.springframework.security.oauth2.core.OAuth2AccessToken; | |||||||
| import org.springframework.security.oauth2.core.OAuth2AuthenticationException; | import org.springframework.security.oauth2.core.OAuth2AuthenticationException; | ||||||
| import org.springframework.security.oauth2.core.OAuth2Error; | import org.springframework.security.oauth2.core.OAuth2Error; | ||||||
| import org.springframework.security.oauth2.core.OAuth2ErrorCodes; | import org.springframework.security.oauth2.core.OAuth2ErrorCodes; | ||||||
|  | import org.springframework.security.oauth2.core.OAuth2RefreshToken; | ||||||
| import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; | import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; | ||||||
| import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationExchange; | import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationExchange; | ||||||
| import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; | import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; | ||||||
| @ -122,8 +123,10 @@ public class OAuth2AuthorizationCodeAuthenticationProviderTests { | |||||||
| 	@Test | 	@Test | ||||||
| 	public void authenticateWhenAuthorizationSuccessResponseThenExchangedForAccessToken() { | 	public void authenticateWhenAuthorizationSuccessResponseThenExchangedForAccessToken() { | ||||||
| 		OAuth2AccessToken accessToken = mock(OAuth2AccessToken.class); | 		OAuth2AccessToken accessToken = mock(OAuth2AccessToken.class); | ||||||
|  | 		OAuth2RefreshToken refreshToken = mock(OAuth2RefreshToken.class); | ||||||
| 		OAuth2AccessTokenResponse accessTokenResponse = mock(OAuth2AccessTokenResponse.class); | 		OAuth2AccessTokenResponse accessTokenResponse = mock(OAuth2AccessTokenResponse.class); | ||||||
| 		when(accessTokenResponse.getAccessToken()).thenReturn(accessToken); | 		when(accessTokenResponse.getAccessToken()).thenReturn(accessToken); | ||||||
|  | 		when(accessTokenResponse.getRefreshToken()).thenReturn(refreshToken); | ||||||
| 		when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(accessTokenResponse); | 		when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(accessTokenResponse); | ||||||
| 
 | 
 | ||||||
| 		OAuth2AuthorizationCodeAuthenticationToken authenticationResult = | 		OAuth2AuthorizationCodeAuthenticationToken authenticationResult = | ||||||
| @ -137,5 +140,6 @@ public class OAuth2AuthorizationCodeAuthenticationProviderTests { | |||||||
| 		assertThat(authenticationResult.getClientRegistration()).isEqualTo(this.clientRegistration); | 		assertThat(authenticationResult.getClientRegistration()).isEqualTo(this.clientRegistration); | ||||||
| 		assertThat(authenticationResult.getAuthorizationExchange()).isEqualTo(this.authorizationExchange); | 		assertThat(authenticationResult.getAuthorizationExchange()).isEqualTo(this.authorizationExchange); | ||||||
| 		assertThat(authenticationResult.getAccessToken()).isEqualTo(accessToken); | 		assertThat(authenticationResult.getAccessToken()).isEqualTo(accessToken); | ||||||
|  | 		assertThat(authenticationResult.getRefreshToken()).isEqualTo(refreshToken); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| /* | /* | ||||||
|  * Copyright 2002-2017 the original author or authors. |  * Copyright 2002-2018 the original author or authors. | ||||||
|  * |  * | ||||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); |  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  * you may not use this file except in compliance with the License. |  * you may not use this file except in compliance with the License. | ||||||
| @ -35,6 +35,7 @@ import org.springframework.security.oauth2.core.OAuth2AccessToken; | |||||||
| import org.springframework.security.oauth2.core.OAuth2AuthenticationException; | import org.springframework.security.oauth2.core.OAuth2AuthenticationException; | ||||||
| import org.springframework.security.oauth2.core.OAuth2Error; | import org.springframework.security.oauth2.core.OAuth2Error; | ||||||
| import org.springframework.security.oauth2.core.OAuth2ErrorCodes; | import org.springframework.security.oauth2.core.OAuth2ErrorCodes; | ||||||
|  | import org.springframework.security.oauth2.core.OAuth2RefreshToken; | ||||||
| import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; | import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; | ||||||
| import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationExchange; | import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationExchange; | ||||||
| import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; | import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; | ||||||
| @ -164,8 +165,10 @@ public class OAuth2LoginAuthenticationProviderTests { | |||||||
| 	@Test | 	@Test | ||||||
| 	public void authenticateWhenLoginSuccessThenReturnAuthentication() { | 	public void authenticateWhenLoginSuccessThenReturnAuthentication() { | ||||||
| 		OAuth2AccessToken accessToken = mock(OAuth2AccessToken.class); | 		OAuth2AccessToken accessToken = mock(OAuth2AccessToken.class); | ||||||
|  | 		OAuth2RefreshToken refreshToken = mock(OAuth2RefreshToken.class); | ||||||
| 		OAuth2AccessTokenResponse accessTokenResponse = mock(OAuth2AccessTokenResponse.class); | 		OAuth2AccessTokenResponse accessTokenResponse = mock(OAuth2AccessTokenResponse.class); | ||||||
| 		when(accessTokenResponse.getAccessToken()).thenReturn(accessToken); | 		when(accessTokenResponse.getAccessToken()).thenReturn(accessToken); | ||||||
|  | 		when(accessTokenResponse.getRefreshToken()).thenReturn(refreshToken); | ||||||
| 		when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(accessTokenResponse); | 		when(this.accessTokenResponseClient.getTokenResponse(any())).thenReturn(accessTokenResponse); | ||||||
| 
 | 
 | ||||||
| 		OAuth2User principal = mock(OAuth2User.class); | 		OAuth2User principal = mock(OAuth2User.class); | ||||||
| @ -185,6 +188,7 @@ public class OAuth2LoginAuthenticationProviderTests { | |||||||
| 		assertThat(authentication.getClientRegistration()).isEqualTo(this.clientRegistration); | 		assertThat(authentication.getClientRegistration()).isEqualTo(this.clientRegistration); | ||||||
| 		assertThat(authentication.getAuthorizationExchange()).isEqualTo(this.authorizationExchange); | 		assertThat(authentication.getAuthorizationExchange()).isEqualTo(this.authorizationExchange); | ||||||
| 		assertThat(authentication.getAccessToken()).isEqualTo(accessToken); | 		assertThat(authentication.getAccessToken()).isEqualTo(accessToken); | ||||||
|  | 		assertThat(authentication.getRefreshToken()).isEqualTo(refreshToken); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Test | 	@Test | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| /* | /* | ||||||
|  * Copyright 2002-2017 the original author or authors. |  * Copyright 2002-2018 the original author or authors. | ||||||
|  * |  * | ||||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); |  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  * you may not use this file except in compliance with the License. |  * you may not use this file except in compliance with the License. | ||||||
| @ -91,6 +91,7 @@ public class NimbusAuthorizationCodeTokenResponseClientTests { | |||||||
| 			"   \"token_type\": \"bearer\",\n" + | 			"   \"token_type\": \"bearer\",\n" + | ||||||
| 			"   \"expires_in\": \"3600\",\n" + | 			"   \"expires_in\": \"3600\",\n" + | ||||||
| 			"   \"scope\": \"openid profile\",\n" + | 			"   \"scope\": \"openid profile\",\n" + | ||||||
|  | 			"	\"refresh_token\": \"refresh-token-1234\",\n" + | ||||||
| 			"   \"custom_parameter_1\": \"custom-value-1\",\n" + | 			"   \"custom_parameter_1\": \"custom-value-1\",\n" + | ||||||
| 			"   \"custom_parameter_2\": \"custom-value-2\"\n" + | 			"   \"custom_parameter_2\": \"custom-value-2\"\n" + | ||||||
| 			"}\n"; | 			"}\n"; | ||||||
| @ -115,6 +116,7 @@ public class NimbusAuthorizationCodeTokenResponseClientTests { | |||||||
| 		assertThat(accessTokenResponse.getAccessToken().getTokenType()).isEqualTo(OAuth2AccessToken.TokenType.BEARER); | 		assertThat(accessTokenResponse.getAccessToken().getTokenType()).isEqualTo(OAuth2AccessToken.TokenType.BEARER); | ||||||
| 		assertThat(accessTokenResponse.getAccessToken().getExpiresAt()).isBetween(expiresAtBefore, expiresAtAfter); | 		assertThat(accessTokenResponse.getAccessToken().getExpiresAt()).isBetween(expiresAtBefore, expiresAtAfter); | ||||||
| 		assertThat(accessTokenResponse.getAccessToken().getScopes()).containsExactly("openid", "profile"); | 		assertThat(accessTokenResponse.getAccessToken().getScopes()).containsExactly("openid", "profile"); | ||||||
|  | 		assertThat(accessTokenResponse.getRefreshToken().getTokenValue()).isEqualTo("refresh-token-1234"); | ||||||
| 		assertThat(accessTokenResponse.getAdditionalParameters().size()).isEqualTo(2); | 		assertThat(accessTokenResponse.getAdditionalParameters().size()).isEqualTo(2); | ||||||
| 		assertThat(accessTokenResponse.getAdditionalParameters()).containsEntry("custom_parameter_1", "custom-value-1"); | 		assertThat(accessTokenResponse.getAdditionalParameters()).containsEntry("custom_parameter_1", "custom-value-1"); | ||||||
| 		assertThat(accessTokenResponse.getAdditionalParameters()).containsEntry("custom_parameter_2", "custom-value-2"); | 		assertThat(accessTokenResponse.getAdditionalParameters()).containsEntry("custom_parameter_2", "custom-value-2"); | ||||||
|  | |||||||
| @ -85,6 +85,7 @@ public class NimbusReactiveAuthorizationCodeTokenResponseClientTests { | |||||||
| 				"   \"token_type\": \"bearer\",\n" + | 				"   \"token_type\": \"bearer\",\n" + | ||||||
| 				"   \"expires_in\": \"3600\",\n" + | 				"   \"expires_in\": \"3600\",\n" + | ||||||
| 				"   \"scope\": \"openid profile\",\n" + | 				"   \"scope\": \"openid profile\",\n" + | ||||||
|  | 				"	\"refresh_token\": \"refresh-token-1234\",\n" + | ||||||
| 				"   \"custom_parameter_1\": \"custom-value-1\",\n" + | 				"   \"custom_parameter_1\": \"custom-value-1\",\n" + | ||||||
| 				"   \"custom_parameter_2\": \"custom-value-2\"\n" + | 				"   \"custom_parameter_2\": \"custom-value-2\"\n" + | ||||||
| 				"}\n"; | 				"}\n"; | ||||||
| @ -102,6 +103,7 @@ public class NimbusReactiveAuthorizationCodeTokenResponseClientTests { | |||||||
| 				OAuth2AccessToken.TokenType.BEARER); | 				OAuth2AccessToken.TokenType.BEARER); | ||||||
| 		assertThat(accessTokenResponse.getAccessToken().getExpiresAt()).isBetween(expiresAtBefore, expiresAtAfter); | 		assertThat(accessTokenResponse.getAccessToken().getExpiresAt()).isBetween(expiresAtBefore, expiresAtAfter); | ||||||
| 		assertThat(accessTokenResponse.getAccessToken().getScopes()).containsExactly("openid", "profile"); | 		assertThat(accessTokenResponse.getAccessToken().getScopes()).containsExactly("openid", "profile"); | ||||||
|  | 		assertThat(accessTokenResponse.getRefreshToken().getTokenValue()).isEqualTo("refresh-token-1234"); | ||||||
| 		assertThat(accessTokenResponse.getAdditionalParameters().size()).isEqualTo(2); | 		assertThat(accessTokenResponse.getAdditionalParameters().size()).isEqualTo(2); | ||||||
| 		assertThat(accessTokenResponse.getAdditionalParameters()).containsEntry("custom_parameter_1", "custom-value-1"); | 		assertThat(accessTokenResponse.getAdditionalParameters()).containsEntry("custom_parameter_1", "custom-value-1"); | ||||||
| 		assertThat(accessTokenResponse.getAdditionalParameters()).containsEntry("custom_parameter_2", "custom-value-2"); | 		assertThat(accessTokenResponse.getAdditionalParameters()).containsEntry("custom_parameter_2", "custom-value-2"); | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| /* | /* | ||||||
|  * Copyright 2002-2017 the original author or authors. |  * Copyright 2002-2018 the original author or authors. | ||||||
|  * |  * | ||||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); |  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  * you may not use this file except in compliance with the License. |  * you may not use this file except in compliance with the License. | ||||||
| @ -37,6 +37,7 @@ import org.springframework.security.oauth2.core.OAuth2AccessToken; | |||||||
| import org.springframework.security.oauth2.core.OAuth2AuthenticationException; | import org.springframework.security.oauth2.core.OAuth2AuthenticationException; | ||||||
| import org.springframework.security.oauth2.core.OAuth2Error; | import org.springframework.security.oauth2.core.OAuth2Error; | ||||||
| import org.springframework.security.oauth2.core.OAuth2ErrorCodes; | import org.springframework.security.oauth2.core.OAuth2ErrorCodes; | ||||||
|  | import org.springframework.security.oauth2.core.OAuth2RefreshToken; | ||||||
| import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; | import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse; | ||||||
| import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationExchange; | import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationExchange; | ||||||
| import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; | import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; | ||||||
| @ -78,6 +79,7 @@ public class OidcAuthorizationCodeAuthenticationProviderTests { | |||||||
| 	private OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> accessTokenResponseClient; | 	private OAuth2AccessTokenResponseClient<OAuth2AuthorizationCodeGrantRequest> accessTokenResponseClient; | ||||||
| 	private OAuth2AccessTokenResponse accessTokenResponse; | 	private OAuth2AccessTokenResponse accessTokenResponse; | ||||||
| 	private OAuth2AccessToken accessToken; | 	private OAuth2AccessToken accessToken; | ||||||
|  | 	private OAuth2RefreshToken refreshToken; | ||||||
| 	private OAuth2UserService<OidcUserRequest, OidcUser> userService; | 	private OAuth2UserService<OidcUserRequest, OidcUser> userService; | ||||||
| 	private OidcAuthorizationCodeAuthenticationProvider authenticationProvider; | 	private OidcAuthorizationCodeAuthenticationProvider authenticationProvider; | ||||||
| 
 | 
 | ||||||
| @ -95,6 +97,7 @@ public class OidcAuthorizationCodeAuthenticationProviderTests { | |||||||
| 		this.accessTokenResponseClient = mock(OAuth2AccessTokenResponseClient.class); | 		this.accessTokenResponseClient = mock(OAuth2AccessTokenResponseClient.class); | ||||||
| 		this.accessTokenResponse = mock(OAuth2AccessTokenResponse.class); | 		this.accessTokenResponse = mock(OAuth2AccessTokenResponse.class); | ||||||
| 		this.accessToken = mock(OAuth2AccessToken.class); | 		this.accessToken = mock(OAuth2AccessToken.class); | ||||||
|  | 		this.refreshToken = mock(OAuth2RefreshToken.class); | ||||||
| 		this.userService = mock(OAuth2UserService.class); | 		this.userService = mock(OAuth2UserService.class); | ||||||
| 		this.authenticationProvider = PowerMockito.spy( | 		this.authenticationProvider = PowerMockito.spy( | ||||||
| 			new OidcAuthorizationCodeAuthenticationProvider(this.accessTokenResponseClient, this.userService)); | 			new OidcAuthorizationCodeAuthenticationProvider(this.accessTokenResponseClient, this.userService)); | ||||||
| @ -109,6 +112,7 @@ public class OidcAuthorizationCodeAuthenticationProviderTests { | |||||||
| 		when(this.authorizationRequest.getRedirectUri()).thenReturn("http://example.com"); | 		when(this.authorizationRequest.getRedirectUri()).thenReturn("http://example.com"); | ||||||
| 		when(this.authorizationResponse.getRedirectUri()).thenReturn("http://example.com"); | 		when(this.authorizationResponse.getRedirectUri()).thenReturn("http://example.com"); | ||||||
| 		when(this.accessTokenResponse.getAccessToken()).thenReturn(this.accessToken); | 		when(this.accessTokenResponse.getAccessToken()).thenReturn(this.accessToken); | ||||||
|  | 		when(this.accessTokenResponse.getRefreshToken()).thenReturn(this.refreshToken); | ||||||
| 		Map<String, Object> additionalParameters = new HashMap<>(); | 		Map<String, Object> additionalParameters = new HashMap<>(); | ||||||
| 		additionalParameters.put(OidcParameterNames.ID_TOKEN, "id-token"); | 		additionalParameters.put(OidcParameterNames.ID_TOKEN, "id-token"); | ||||||
| 		when(this.accessTokenResponse.getAdditionalParameters()).thenReturn(additionalParameters); | 		when(this.accessTokenResponse.getAdditionalParameters()).thenReturn(additionalParameters); | ||||||
| @ -365,6 +369,7 @@ public class OidcAuthorizationCodeAuthenticationProviderTests { | |||||||
| 		assertThat(authentication.getClientRegistration()).isEqualTo(this.clientRegistration); | 		assertThat(authentication.getClientRegistration()).isEqualTo(this.clientRegistration); | ||||||
| 		assertThat(authentication.getAuthorizationExchange()).isEqualTo(this.authorizationExchange); | 		assertThat(authentication.getAuthorizationExchange()).isEqualTo(this.authorizationExchange); | ||||||
| 		assertThat(authentication.getAccessToken()).isEqualTo(this.accessToken); | 		assertThat(authentication.getAccessToken()).isEqualTo(this.accessToken); | ||||||
|  | 		assertThat(authentication.getRefreshToken()).isEqualTo(this.refreshToken); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Test | 	@Test | ||||||
|  | |||||||
| @ -41,6 +41,7 @@ import org.springframework.security.oauth2.core.OAuth2AccessToken; | |||||||
| import org.springframework.security.oauth2.core.OAuth2AuthenticationException; | import org.springframework.security.oauth2.core.OAuth2AuthenticationException; | ||||||
| import org.springframework.security.oauth2.core.OAuth2Error; | import org.springframework.security.oauth2.core.OAuth2Error; | ||||||
| import org.springframework.security.oauth2.core.OAuth2ErrorCodes; | import org.springframework.security.oauth2.core.OAuth2ErrorCodes; | ||||||
|  | import org.springframework.security.oauth2.core.OAuth2RefreshToken; | ||||||
| import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationExchange; | import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationExchange; | ||||||
| import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; | import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; | ||||||
| import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; | import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; | ||||||
| @ -238,6 +239,7 @@ public class OAuth2AuthorizationCodeGrantFilterTests { | |||||||
| 		assertThat(authorizedClient.getClientRegistration()).isEqualTo(this.registration1); | 		assertThat(authorizedClient.getClientRegistration()).isEqualTo(this.registration1); | ||||||
| 		assertThat(authorizedClient.getPrincipalName()).isEqualTo(this.principalName1); | 		assertThat(authorizedClient.getPrincipalName()).isEqualTo(this.principalName1); | ||||||
| 		assertThat(authorizedClient.getAccessToken()).isNotNull(); | 		assertThat(authorizedClient.getAccessToken()).isNotNull(); | ||||||
|  | 		assertThat(authorizedClient.getRefreshToken()).isNotNull(); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Test | 	@Test | ||||||
| @ -299,6 +301,7 @@ public class OAuth2AuthorizationCodeGrantFilterTests { | |||||||
| 		when(authentication.getClientRegistration()).thenReturn(registration); | 		when(authentication.getClientRegistration()).thenReturn(registration); | ||||||
| 		when(authentication.getAuthorizationExchange()).thenReturn(mock(OAuth2AuthorizationExchange.class)); | 		when(authentication.getAuthorizationExchange()).thenReturn(mock(OAuth2AuthorizationExchange.class)); | ||||||
| 		when(authentication.getAccessToken()).thenReturn(mock(OAuth2AccessToken.class)); | 		when(authentication.getAccessToken()).thenReturn(mock(OAuth2AccessToken.class)); | ||||||
|  | 		when(authentication.getRefreshToken()).thenReturn(mock(OAuth2RefreshToken.class)); | ||||||
| 		when(this.authenticationManager.authenticate(any(Authentication.class))).thenReturn(authentication); | 		when(this.authenticationManager.authenticate(any(Authentication.class))).thenReturn(authentication); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| /* | /* | ||||||
|  * Copyright 2002-2017 the original author or authors. |  * Copyright 2002-2018 the original author or authors. | ||||||
|  * |  * | ||||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); |  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  * you may not use this file except in compliance with the License. |  * you may not use this file except in compliance with the License. | ||||||
| @ -40,6 +40,7 @@ import org.springframework.security.oauth2.core.ClientAuthenticationMethod; | |||||||
| import org.springframework.security.oauth2.core.OAuth2AccessToken; | import org.springframework.security.oauth2.core.OAuth2AccessToken; | ||||||
| import org.springframework.security.oauth2.core.OAuth2AuthenticationException; | import org.springframework.security.oauth2.core.OAuth2AuthenticationException; | ||||||
| import org.springframework.security.oauth2.core.OAuth2ErrorCodes; | import org.springframework.security.oauth2.core.OAuth2ErrorCodes; | ||||||
|  | import org.springframework.security.oauth2.core.OAuth2RefreshToken; | ||||||
| import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationExchange; | import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationExchange; | ||||||
| import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; | import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest; | ||||||
| import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; | import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames; | ||||||
| @ -281,6 +282,7 @@ public class OAuth2LoginAuthenticationFilterTests { | |||||||
| 		assertThat(authorizedClient.getClientRegistration()).isEqualTo(this.registration1); | 		assertThat(authorizedClient.getClientRegistration()).isEqualTo(this.registration1); | ||||||
| 		assertThat(authorizedClient.getPrincipalName()).isEqualTo(this.principalName1); | 		assertThat(authorizedClient.getPrincipalName()).isEqualTo(this.principalName1); | ||||||
| 		assertThat(authorizedClient.getAccessToken()).isNotNull(); | 		assertThat(authorizedClient.getAccessToken()).isNotNull(); | ||||||
|  | 		assertThat(authorizedClient.getRefreshToken()).isNotNull(); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@Test | 	@Test | ||||||
| @ -328,6 +330,7 @@ public class OAuth2LoginAuthenticationFilterTests { | |||||||
| 		when(loginAuthentication.getClientRegistration()).thenReturn(registration); | 		when(loginAuthentication.getClientRegistration()).thenReturn(registration); | ||||||
| 		when(loginAuthentication.getAuthorizationExchange()).thenReturn(mock(OAuth2AuthorizationExchange.class)); | 		when(loginAuthentication.getAuthorizationExchange()).thenReturn(mock(OAuth2AuthorizationExchange.class)); | ||||||
| 		when(loginAuthentication.getAccessToken()).thenReturn(mock(OAuth2AccessToken.class)); | 		when(loginAuthentication.getAccessToken()).thenReturn(mock(OAuth2AccessToken.class)); | ||||||
|  | 		when(loginAuthentication.getRefreshToken()).thenReturn(mock(OAuth2RefreshToken.class)); | ||||||
| 		when(this.authenticationManager.authenticate(any(Authentication.class))).thenReturn(loginAuthentication); | 		when(this.authenticationManager.authenticate(any(Authentication.class))).thenReturn(loginAuthentication); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| /* | /* | ||||||
|  * Copyright 2002-2017 the original author or authors. |  * Copyright 2002-2018 the original author or authors. | ||||||
|  * |  * | ||||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); |  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  * you may not use this file except in compliance with the License. |  * you may not use this file except in compliance with the License. | ||||||
| @ -37,6 +37,7 @@ public final class AuthorizationGrantType implements Serializable { | |||||||
| 	private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; | 	private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID; | ||||||
| 	public static final AuthorizationGrantType AUTHORIZATION_CODE = new AuthorizationGrantType("authorization_code"); | 	public static final AuthorizationGrantType AUTHORIZATION_CODE = new AuthorizationGrantType("authorization_code"); | ||||||
| 	public static final AuthorizationGrantType IMPLICIT = new AuthorizationGrantType("implicit"); | 	public static final AuthorizationGrantType IMPLICIT = new AuthorizationGrantType("implicit"); | ||||||
|  | 	public static final AuthorizationGrantType REFRESH_TOKEN = new AuthorizationGrantType("refresh_token"); | ||||||
| 	private final String value; | 	private final String value; | ||||||
| 
 | 
 | ||||||
| 	/** | 	/** | ||||||
|  | |||||||
| @ -0,0 +1,46 @@ | |||||||
|  | /* | ||||||
|  |  * Copyright 2002-2018 the original author or authors. | ||||||
|  |  * | ||||||
|  |  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  |  * you may not use this file except in compliance with the License. | ||||||
|  |  * You may obtain a copy of the License at | ||||||
|  |  * | ||||||
|  |  *      http://www.apache.org/licenses/LICENSE-2.0 | ||||||
|  |  * | ||||||
|  |  * Unless required by applicable law or agreed to in writing, software | ||||||
|  |  * distributed under the License is distributed on an "AS IS" BASIS, | ||||||
|  |  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||||
|  |  * See the License for the specific language governing permissions and | ||||||
|  |  * limitations under the License. | ||||||
|  |  */ | ||||||
|  | package org.springframework.security.oauth2.core; | ||||||
|  | 
 | ||||||
|  | import java.time.Instant; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * An implementation of an {@link AbstractOAuth2Token} representing an OAuth 2.0 Refresh Token. | ||||||
|  |  * | ||||||
|  |  * <p> | ||||||
|  |  * A refresh token is a credential that represents an authorization | ||||||
|  |  * granted by the resource owner to the client. | ||||||
|  |  * It is used by the client to obtain a new access token when the current access token | ||||||
|  |  * becomes invalid or expires, or to obtain additional access tokens with identical or narrower scope. | ||||||
|  |  * | ||||||
|  |  * @author Joe Grandja | ||||||
|  |  * @since 5.1 | ||||||
|  |  * @see OAuth2AccessToken | ||||||
|  |  * @see <a target="_blank" href="https://tools.ietf.org/html/rfc6749#section-1.5">Section 1.5 Refresh Token</a> | ||||||
|  |  */ | ||||||
|  | public class OAuth2RefreshToken extends AbstractOAuth2Token { | ||||||
|  | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Constructs an {@code OAuth2RefreshToken} using the provided parameters. | ||||||
|  | 	 * | ||||||
|  | 	 * @param tokenValue the token value | ||||||
|  | 	 * @param issuedAt the time at which the token was issued | ||||||
|  | 	 * @param expiresAt the expiration time on or after which the token MUST NOT be accepted | ||||||
|  | 	 */ | ||||||
|  | 	public OAuth2RefreshToken(String tokenValue, Instant issuedAt, Instant expiresAt) { | ||||||
|  | 		super(tokenValue, issuedAt, expiresAt); | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @ -1,5 +1,5 @@ | |||||||
| /* | /* | ||||||
|  * Copyright 2002-2017 the original author or authors. |  * Copyright 2002-2018 the original author or authors. | ||||||
|  * |  * | ||||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); |  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  * you may not use this file except in compliance with the License. |  * you may not use this file except in compliance with the License. | ||||||
| @ -15,8 +15,11 @@ | |||||||
|  */ |  */ | ||||||
| package org.springframework.security.oauth2.core.endpoint; | package org.springframework.security.oauth2.core.endpoint; | ||||||
| 
 | 
 | ||||||
|  | import org.springframework.lang.Nullable; | ||||||
| import org.springframework.security.oauth2.core.OAuth2AccessToken; | import org.springframework.security.oauth2.core.OAuth2AccessToken; | ||||||
|  | import org.springframework.security.oauth2.core.OAuth2RefreshToken; | ||||||
| import org.springframework.util.CollectionUtils; | import org.springframework.util.CollectionUtils; | ||||||
|  | import org.springframework.util.StringUtils; | ||||||
| 
 | 
 | ||||||
| import java.time.Instant; | import java.time.Instant; | ||||||
| import java.util.Collections; | import java.util.Collections; | ||||||
| @ -29,10 +32,12 @@ import java.util.Set; | |||||||
|  * @author Joe Grandja |  * @author Joe Grandja | ||||||
|  * @since 5.0 |  * @since 5.0 | ||||||
|  * @see OAuth2AccessToken |  * @see OAuth2AccessToken | ||||||
|  |  * @see OAuth2RefreshToken | ||||||
|  * @see <a target="_blank" href="https://tools.ietf.org/html/rfc6749#section-5.1">Section 5.1 Access Token Response</a> |  * @see <a target="_blank" href="https://tools.ietf.org/html/rfc6749#section-5.1">Section 5.1 Access Token Response</a> | ||||||
|  */ |  */ | ||||||
| public final class OAuth2AccessTokenResponse { | public final class OAuth2AccessTokenResponse { | ||||||
| 	private OAuth2AccessToken accessToken; | 	private OAuth2AccessToken accessToken; | ||||||
|  | 	private OAuth2RefreshToken refreshToken; | ||||||
| 	private Map<String, Object> additionalParameters; | 	private Map<String, Object> additionalParameters; | ||||||
| 
 | 
 | ||||||
| 	private OAuth2AccessTokenResponse() { | 	private OAuth2AccessTokenResponse() { | ||||||
| @ -47,6 +52,16 @@ public final class OAuth2AccessTokenResponse { | |||||||
| 		return this.accessToken; | 		return this.accessToken; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	/** | ||||||
|  | 	 * Returns the {@link OAuth2RefreshToken Refresh Token}. | ||||||
|  | 	 * | ||||||
|  | 	 * @since 5.1 | ||||||
|  | 	 * @return the {@link OAuth2RefreshToken} | ||||||
|  | 	 */ | ||||||
|  | 	public @Nullable OAuth2RefreshToken getRefreshToken() { | ||||||
|  | 		return this.refreshToken; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	/** | 	/** | ||||||
| 	 * Returns the additional parameters returned in the response. | 	 * Returns the additional parameters returned in the response. | ||||||
| 	 * | 	 * | ||||||
| @ -74,6 +89,7 @@ public final class OAuth2AccessTokenResponse { | |||||||
| 		private OAuth2AccessToken.TokenType tokenType; | 		private OAuth2AccessToken.TokenType tokenType; | ||||||
| 		private long expiresIn; | 		private long expiresIn; | ||||||
| 		private Set<String> scopes; | 		private Set<String> scopes; | ||||||
|  | 		private String refreshToken; | ||||||
| 		private Map<String, Object> additionalParameters; | 		private Map<String, Object> additionalParameters; | ||||||
| 
 | 
 | ||||||
| 		private Builder(String tokenValue) { | 		private Builder(String tokenValue) { | ||||||
| @ -113,6 +129,17 @@ public final class OAuth2AccessTokenResponse { | |||||||
| 			return this; | 			return this; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | 		/** | ||||||
|  | 		 * Sets the refresh token associated to the access token. | ||||||
|  | 		 * | ||||||
|  | 		 * @param refreshToken the refresh token associated to the access token. | ||||||
|  | 		 * @return the {@link Builder} | ||||||
|  | 		 */ | ||||||
|  | 		public Builder refreshToken(String refreshToken) { | ||||||
|  | 			this.refreshToken = refreshToken; | ||||||
|  | 			return this; | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
| 		/** | 		/** | ||||||
| 		 * Sets the additional parameters returned in the response. | 		 * Sets the additional parameters returned in the response. | ||||||
| 		 * | 		 * | ||||||
| @ -142,6 +169,14 @@ public final class OAuth2AccessTokenResponse { | |||||||
| 			OAuth2AccessTokenResponse accessTokenResponse = new OAuth2AccessTokenResponse(); | 			OAuth2AccessTokenResponse accessTokenResponse = new OAuth2AccessTokenResponse(); | ||||||
| 			accessTokenResponse.accessToken = new OAuth2AccessToken( | 			accessTokenResponse.accessToken = new OAuth2AccessToken( | ||||||
| 				this.tokenType, this.tokenValue, issuedAt, expiresAt, this.scopes); | 				this.tokenType, this.tokenValue, issuedAt, expiresAt, this.scopes); | ||||||
|  | 			if (StringUtils.hasText(this.refreshToken)) { | ||||||
|  | 				// The Access Token response does not return an expires_in for the Refresh Token, | ||||||
|  | 				// therefore, we'll default to +1 second from issuedAt time. | ||||||
|  | 				// NOTE: | ||||||
|  | 				// The expiry or invalidity of a Refresh Token can only be determined by performing | ||||||
|  | 				// the refresh_token grant and if it fails than likely it has expired or has been invalidated. | ||||||
|  | 				accessTokenResponse.refreshToken = new OAuth2RefreshToken(this.refreshToken, issuedAt, issuedAt.plusSeconds(1)); | ||||||
|  | 			} | ||||||
| 			accessTokenResponse.additionalParameters = Collections.unmodifiableMap( | 			accessTokenResponse.additionalParameters = Collections.unmodifiableMap( | ||||||
| 				CollectionUtils.isEmpty(this.additionalParameters) ? Collections.emptyMap() : this.additionalParameters); | 				CollectionUtils.isEmpty(this.additionalParameters) ? Collections.emptyMap() : this.additionalParameters); | ||||||
| 			return accessTokenResponse; | 			return accessTokenResponse; | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| /* | /* | ||||||
|  * Copyright 2002-2017 the original author or authors. |  * Copyright 2002-2018 the original author or authors. | ||||||
|  * |  * | ||||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); |  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  * you may not use this file except in compliance with the License. |  * you may not use this file except in compliance with the License. | ||||||
| @ -40,4 +40,9 @@ public class AuthorizationGrantTypeTests { | |||||||
| 	public void getValueWhenImplicitGrantTypeThenReturnImplicit() { | 	public void getValueWhenImplicitGrantTypeThenReturnImplicit() { | ||||||
| 		assertThat(AuthorizationGrantType.IMPLICIT.getValue()).isEqualTo("implicit"); | 		assertThat(AuthorizationGrantType.IMPLICIT.getValue()).isEqualTo("implicit"); | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	@Test | ||||||
|  | 	public void getValueWhenRefreshTokenGrantTypeThenReturnRefreshToken() { | ||||||
|  | 		assertThat(AuthorizationGrantType.REFRESH_TOKEN.getValue()).isEqualTo("refresh_token"); | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| /* | /* | ||||||
|  * Copyright 2002-2017 the original author or authors. |  * Copyright 2002-2018 the original author or authors. | ||||||
|  * |  * | ||||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); |  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||||
|  * you may not use this file except in compliance with the License. |  * you may not use this file except in compliance with the License. | ||||||
| @ -35,6 +35,7 @@ import static org.assertj.core.api.Assertions.assertThat; | |||||||
|  */ |  */ | ||||||
| public class OAuth2AccessTokenResponseTests { | public class OAuth2AccessTokenResponseTests { | ||||||
| 	private static final String TOKEN_VALUE = "access-token"; | 	private static final String TOKEN_VALUE = "access-token"; | ||||||
|  | 	private static final String REFRESH_TOKEN_VALUE = "refresh-token"; | ||||||
| 	private static final long EXPIRES_IN = Instant.now().plusSeconds(5).toEpochMilli(); | 	private static final long EXPIRES_IN = Instant.now().plusSeconds(5).toEpochMilli(); | ||||||
| 
 | 
 | ||||||
| 	@Test(expected = IllegalArgumentException.class) | 	@Test(expected = IllegalArgumentException.class) | ||||||
| @ -88,6 +89,7 @@ public class OAuth2AccessTokenResponseTests { | |||||||
| 			.tokenType(OAuth2AccessToken.TokenType.BEARER) | 			.tokenType(OAuth2AccessToken.TokenType.BEARER) | ||||||
| 			.expiresIn(expiresAt.toEpochMilli()) | 			.expiresIn(expiresAt.toEpochMilli()) | ||||||
| 			.scopes(scopes) | 			.scopes(scopes) | ||||||
|  | 			.refreshToken(REFRESH_TOKEN_VALUE) | ||||||
| 			.additionalParameters(additionalParameters) | 			.additionalParameters(additionalParameters) | ||||||
| 			.build(); | 			.build(); | ||||||
| 
 | 
 | ||||||
| @ -97,6 +99,7 @@ public class OAuth2AccessTokenResponseTests { | |||||||
| 		assertThat(tokenResponse.getAccessToken().getIssuedAt()).isNotNull(); | 		assertThat(tokenResponse.getAccessToken().getIssuedAt()).isNotNull(); | ||||||
| 		assertThat(tokenResponse.getAccessToken().getExpiresAt()).isAfterOrEqualTo(expiresAt); | 		assertThat(tokenResponse.getAccessToken().getExpiresAt()).isAfterOrEqualTo(expiresAt); | ||||||
| 		assertThat(tokenResponse.getAccessToken().getScopes()).isEqualTo(scopes); | 		assertThat(tokenResponse.getAccessToken().getScopes()).isEqualTo(scopes); | ||||||
|  | 		assertThat(tokenResponse.getRefreshToken().getTokenValue()).isEqualTo(REFRESH_TOKEN_VALUE); | ||||||
| 		assertThat(tokenResponse.getAdditionalParameters()).isEqualTo(additionalParameters); | 		assertThat(tokenResponse.getAdditionalParameters()).isEqualTo(additionalParameters); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user