-
Notifications
You must be signed in to change notification settings - Fork 827
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix/user token #2193
Fix/user token #2193
Changes from all commits
f87b6b1
c762b0f
3e93cae
b105d77
07ad972
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,14 +14,18 @@ | |
|
||
package org.cloudfoundry.identity.uaa.oauth.token; | ||
|
||
import org.cloudfoundry.identity.uaa.authentication.ClientDetailsAuthenticationProvider; | ||
import org.cloudfoundry.identity.uaa.oauth.UaaOauth2Authentication; | ||
import org.cloudfoundry.identity.uaa.zone.MultitenantClientServices; | ||
import org.cloudfoundry.identity.uaa.zone.IdentityZoneHolder; | ||
import org.springframework.security.authentication.InsufficientAuthenticationException; | ||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; | ||
import org.springframework.security.core.Authentication; | ||
import org.springframework.security.core.AuthenticationException; | ||
import org.springframework.security.core.context.SecurityContextHolder; | ||
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; | ||
import org.springframework.security.oauth2.common.OAuth2AccessToken; | ||
import org.springframework.security.oauth2.common.exceptions.InvalidClientException; | ||
import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; | ||
import org.springframework.security.oauth2.provider.ClientDetails; | ||
import org.springframework.security.oauth2.provider.OAuth2Authentication; | ||
|
@@ -40,14 +44,17 @@ public class UserTokenGranter extends AbstractTokenGranter { | |
|
||
private MultitenantClientServices clientDetailsService; | ||
private RevocableTokenProvisioning tokenStore; | ||
private ClientDetailsAuthenticationProvider clientAuthenticationProvider; | ||
|
||
public UserTokenGranter(AuthorizationServerTokenServices tokenServices, | ||
MultitenantClientServices clientDetailsService, | ||
OAuth2RequestFactory requestFactory, | ||
RevocableTokenProvisioning tokenStore) { | ||
RevocableTokenProvisioning tokenStore, | ||
ClientDetailsAuthenticationProvider clientAuthenticationProvider) { | ||
super(tokenServices, clientDetailsService, requestFactory, TokenConstants.GRANT_TYPE_USER_TOKEN); | ||
this.clientDetailsService = clientDetailsService; | ||
this.tokenStore = tokenStore; | ||
this.clientAuthenticationProvider = clientAuthenticationProvider; | ||
} | ||
|
||
@Override | ||
|
@@ -97,6 +104,16 @@ protected Authentication validateRequest(TokenRequest request) { | |
ClientDetails receiving = clientDetailsService.loadClientByClientId(request.getRequestParameters().get(CLIENT_ID), IdentityZoneHolder.get().getId()); | ||
super.validateGrantType(GRANT_TYPE_REFRESH_TOKEN, receiving); | ||
|
||
//7. receiving client must have a client secret | ||
try { | ||
UsernamePasswordAuthenticationToken clientAuth = | ||
new UsernamePasswordAuthenticationToken(request.getRequestParameters().get(CLIENT_ID), ""); | ||
clientAuthenticationProvider.authenticate(clientAuth); | ||
throw new InvalidClientException("Grant type is not allowed for this client"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This code is very difficult to understand. It seems that an exception is expected in order for the grant to be validated. Could this (and perhaps the authenticate method that's called here) be restructured so that the requirement this is validating is easier to understand from looking at the code? |
||
} | ||
catch (AuthenticationException ignored) { | ||
} | ||
|
||
return oauth2Authentication.getUserAuthentication(); | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,6 +14,7 @@ | |
|
||
package org.cloudfoundry.identity.uaa.oauth.token; | ||
|
||
import org.cloudfoundry.identity.uaa.authentication.ClientDetailsAuthenticationProvider; | ||
import org.cloudfoundry.identity.uaa.zone.MultitenantClientServices; | ||
import org.hamcrest.Matchers; | ||
import org.junit.Before; | ||
|
@@ -43,7 +44,8 @@ public void setup() { | |
mock(AuthorizationServerTokenServices.class), | ||
mock(MultitenantClientServices.class), | ||
mock(OAuth2RequestFactory.class), | ||
mock(RevocableTokenProvisioning.class) | ||
mock(RevocableTokenProvisioning.class), | ||
mock(ClientDetailsAuthenticationProvider.class) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this would not be needed then |
||
); | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,6 +14,7 @@ | |
|
||
package org.cloudfoundry.identity.uaa.oauth.token; | ||
|
||
import org.cloudfoundry.identity.uaa.authentication.ClientDetailsAuthenticationProvider; | ||
import org.cloudfoundry.identity.uaa.authentication.UaaAuthentication; | ||
import org.cloudfoundry.identity.uaa.oauth.UaaOauth2Authentication; | ||
import org.cloudfoundry.identity.uaa.zone.MultitenantClientServices; | ||
|
@@ -22,7 +23,9 @@ | |
import org.junit.Before; | ||
import org.junit.Test; | ||
import org.springframework.security.authentication.InsufficientAuthenticationException; | ||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; | ||
import org.springframework.security.core.Authentication; | ||
import org.springframework.security.authentication.BadCredentialsException; | ||
import org.springframework.security.core.context.SecurityContextHolder; | ||
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; | ||
import org.springframework.security.oauth2.common.DefaultOAuth2RefreshToken; | ||
|
@@ -42,6 +45,7 @@ | |
import static org.junit.Assert.assertEquals; | ||
import static org.junit.Assert.assertNull; | ||
import static org.junit.Assert.assertSame; | ||
import static org.mockito.ArgumentMatchers.any; | ||
import static org.mockito.ArgumentMatchers.anyString; | ||
import static org.mockito.ArgumentMatchers.anyInt; | ||
import static org.mockito.ArgumentMatchers.eq; | ||
|
@@ -66,6 +70,7 @@ public class UserTokenGranterTest { | |
private BaseClientDetails requestingClient; | ||
private BaseClientDetails receivingClient; | ||
private RevocableTokenProvisioning tokenStore; | ||
private ClientDetailsAuthenticationProvider clientAuthenticationProvider; | ||
|
||
@Before | ||
public void setup() { | ||
|
@@ -74,13 +79,15 @@ public void setup() { | |
requestFactory = mock(OAuth2RequestFactory.class); | ||
authentication = mock(UaaOauth2Authentication.class); | ||
tokenStore = mock(RevocableTokenProvisioning.class); | ||
clientAuthenticationProvider = mock(ClientDetailsAuthenticationProvider.class); | ||
|
||
userAuthentication = mock(UaaAuthentication.class); | ||
granter = new UserTokenGranter( | ||
tokenServices, | ||
clientDetailsService, | ||
requestFactory, | ||
tokenStore | ||
tokenStore, | ||
clientAuthenticationProvider | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this would not be needed then |
||
); | ||
SecurityContextHolder.getContext().setAuthentication(authentication); | ||
|
||
|
@@ -94,8 +101,6 @@ public void setup() { | |
requestParameters.put(CLIENT_ID, receivingClient.getClientId()); | ||
tokenRequest = new PublicTokenRequest(); | ||
tokenRequest.setRequestParameters(requestParameters); | ||
|
||
|
||
} | ||
|
||
@After | ||
|
@@ -168,7 +173,8 @@ public void ensure_client_gets_swapped() { | |
tokenServices, | ||
clientDetailsService, | ||
requestFactory, | ||
tokenStore | ||
tokenStore, | ||
clientAuthenticationProvider | ||
) { | ||
@Override | ||
protected DefaultOAuth2AccessToken prepareForSerialization(DefaultOAuth2AccessToken token) { | ||
|
@@ -188,6 +194,15 @@ protected Authentication validateRequest(TokenRequest request) { | |
|
||
@Test | ||
public void happy_day() { | ||
when(clientAuthenticationProvider.authenticate(any(UsernamePasswordAuthenticationToken.class))) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What's the purpose of this test? It was a little bit confusing before this change , but now with a mock that throws an exception but the name "happy_day" I can't tell if this is a happy path test or not. |
||
.thenThrow(new BadCredentialsException("Bad credentials")); | ||
missing_parameter("non existent"); | ||
} | ||
|
||
@Test(expected = InvalidClientException.class) | ||
public void test_client_no_secret() { | ||
when(clientAuthenticationProvider.authenticate(any(UsernamePasswordAuthenticationToken.class))) | ||
.thenReturn(null); | ||
missing_parameter("non existent"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I know this method was already there, but can we improve the name of missing_parameter()? Maybe validate_with_missing_parameter()? |
||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I vote to perform the check in extra method, means, check if secret "" is set to client. I assume you agree if I provide a PR which would perform the check for you?