Skip to content
This repository has been archived by the owner on May 31, 2022. It is now read-only.

Commit

Permalink
SECOAUTH-154: added rough draft of implicit token provider on client
Browse files Browse the repository at this point in the history
  • Loading branch information
dsyer committed Nov 7, 2011
1 parent 3b90b0a commit 177545c
Show file tree
Hide file tree
Showing 28 changed files with 604 additions and 282 deletions.
Expand Up @@ -61,17 +61,17 @@
<oauth:resource-server id="resourceServerFilter" resource-id="sparklr" token-services-ref="tokenServices" />

<oauth:client-details-service id="clientDetails">
<oauth:client clientId="my-trusted-client" authorizedGrantTypes="password,authorization_code,refresh_token,implicit"
<oauth:client client-id="my-trusted-client" authorized-grant-types="password,authorization_code,refresh_token,implicit"
authorities="ROLE_CLIENT, ROLE_TRUSTED_CLIENT" scope="read,write,trust" />
<oauth:client clientId="my-trusted-client-with-secret" authorizedGrantTypes="password,authorization_code,refresh_token"
<oauth:client client-id="my-trusted-client-with-secret" authorized-grant-types="password,authorization_code,refresh_token"
secret="somesecret" authorities="ROLE_CLIENT, ROLE_TRUSTED_CLIENT" />
<oauth:client clientId="my-less-trusted-client" authorizedGrantTypes="authorization_code,implicit"
<oauth:client client-id="my-less-trusted-client" authorized-grant-types="authorization_code,implicit"
authorities="ROLE_CLIENT" />
<oauth:client clientId="my-client-with-registered-redirect" authorizedGrantTypes="authorization_code,client_credentials"
<oauth:client client-id="my-client-with-registered-redirect" authorized-grant-types="authorization_code,client_credentials"
authorities="ROLE_CLIENT" redirect-uri="http://anywhere" scope="trust" />
<oauth:client clientId="my-untrusted-client-with-registered-redirect" authorizedGrantTypes="authorization_code"
<oauth:client client-id="my-untrusted-client-with-registered-redirect" authorized-grant-types="authorization_code"
authorities="ROLE_CLIENT" redirect-uri="http://anywhere" scope="read" />
<oauth:client clientId="tonr" resource-ids="sparklr" authorizedGrantTypes="authorization_code"
<oauth:client client-id="tonr" resource-ids="sparklr" authorized-grant-types="authorization_code"
authorities="ROLE_CLIENT" scope="read,write" secret="secret" />
</oauth:client-details-service>

Expand Down
Expand Up @@ -17,7 +17,6 @@
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.security.oauth2.client.context.OAuth2ClientContext;
import org.springframework.security.oauth2.client.context.OAuth2ClientContextHolder;
import org.springframework.security.oauth2.client.filter.OAuth2ClientContextImpl;
import org.springframework.security.oauth2.client.http.OAuth2AccessTokenRequiredException;
import org.springframework.security.oauth2.client.provider.token.OAuth2ClientTokenServices;
import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
Expand Down Expand Up @@ -68,7 +67,7 @@ public void startElement(String uri, String localName, String qName, Attributes
if (context != null) {
// TODO: this one is kind of a hack for this application
// the problem is that the sparklr photos page doesn't remove the 'code=' request parameter.
((OAuth2ClientContextImpl) context).setAuthorizationCode(null);
// ((OAuth2ClientContextImpl) context).setAuthorizationCode(null);
}
// clear any stored access tokens...
tokenServices.removeToken(SecurityContextHolder.getContext().getAuthentication(), resource);
Expand Down
Expand Up @@ -9,7 +9,6 @@
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.security.oauth2.client.context.OAuth2ClientContext;
import org.springframework.security.oauth2.client.context.OAuth2ClientContextHolder;
import org.springframework.security.oauth2.client.filter.OAuth2ClientContextImpl;
import org.springframework.security.oauth2.client.http.OAuth2AccessTokenRequiredException;
import org.springframework.security.oauth2.client.provider.token.OAuth2ClientTokenServices;
import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
Expand Down Expand Up @@ -49,7 +48,7 @@ public String photos(Model model) throws Exception {
if (context != null) {
// this one is kind of a hack for this application
// the problem is that the facebook friends page doesn't remove the 'code=' request parameter.
((OAuth2ClientContextImpl) context).setAuthorizationCode(null);
// ((OAuth2ClientContext) context).setAuthorizationCode(null);
}
// clear any stored access tokens...
tokenServices.removeToken(SecurityContextHolder.getContext().getAuthentication(), resource);
Expand Down
16 changes: 8 additions & 8 deletions samples/oauth2/tonr/src/main/webapp/WEB-INF/spring-servlet.xml
Expand Up @@ -38,18 +38,18 @@
<bean id="oauth2TokenServices" class="org.springframework.security.oauth2.client.provider.token.InMemoryOAuth2ClientTokenServices" />

<!--define an oauth 2 resource for sparklr -->
<oauth:resource id="sparklr" type="authorization_code" clientId="tonr" clientSecret="secret"
accessTokenUri="${accessTokenUri}" userAuthorizationUri="${userAuthorizationUri}" scope="read" />
<oauth:resource id="sparklr" type="authorization_code" client-id="tonr" client-secret="secret"
access-token-uri="${accessTokenUri}" user-authorization-uri="${userAuthorizationUri}" scope="read" />

<!--define an oauth 2 resource for trusted client on sparklr -->
<oauth:resource id="trusted" type="client_credentials" clientId="my-client-with-registered-redirect"
accessTokenUri="${accessTokenUri}" scope="trust" />
<oauth:resource id="trusted" type="client_credentials" client-id="my-client-with-registered-redirect"
access-token-uri="${accessTokenUri}" scope="trust" />

<!--define an oauth 2 resource for facebook. according to the facebook docs, the 'clientId' is the App ID, and the 'clientSecret'
<!--define an oauth 2 resource for facebook. according to the facebook docs, the 'client-id' is the App ID, and the 'client-secret'
is the App Secret -->
<oauth:resource id="facebook" type="authorization_code" clientId="162646850439461" clientSecret="560ad91d992d60298ae6c7f717c8fc93"
bearerTokenMethod="query" accessTokenUri="https://graph.facebook.com/oauth/access_token" userAuthorizationUri="https://www.facebook.com/dialog/oauth"
bearerTokenName="oauth_token" />
<oauth:resource id="facebook" type="authorization_code" client-id="162646850439461" client-secret="560ad91d992d60298ae6c7f717c8fc93"
authentication-scheme="query" access-token-uri="https://graph.facebook.com/oauth/access_token" user-authorization-uri="https://www.facebook.com/dialog/oauth"
token-name="oauth_token" />

<mvc:default-servlet-handler />

Expand Down
Expand Up @@ -137,7 +137,7 @@ public Statement apply(Statement base, FrameworkMethod method, Object target) {
HttpURLConnection.setFollowRedirects(false);
boolean online = false;
try {
client.getForEntity(new UriTemplate(getUrl("/sparklr/oauth/authorize")).toString(), String.class);
client.getForEntity(new UriTemplate(getUrl("/sparklr/login.jsp")).toString(), String.class);
online = true;
logger.info("Basic connectivity test passed");
} catch (RestClientException e) {
Expand Down
Expand Up @@ -18,8 +18,9 @@
import org.springframework.http.HttpStatus;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.security.oauth2.client.UserRedirectRequiredException;
import org.springframework.security.oauth2.client.context.OAuth2ClientContext;
import org.springframework.security.oauth2.client.context.OAuth2ClientContextHolder;
import org.springframework.security.oauth2.client.filter.OAuth2ClientContextImpl;
import org.springframework.security.oauth2.client.provider.AccessTokenRequest;
import org.springframework.security.oauth2.client.provider.grant.client.ClientCredentialsAccessTokenProvider;
import org.springframework.security.oauth2.client.provider.grant.client.ClientCredentialsResourceDetails;
import org.springframework.security.oauth2.client.provider.grant.code.AuthorizationCodeAccessTokenProvider;
Expand Down Expand Up @@ -68,7 +69,7 @@ public void testCannotConnectWithoutToken() throws Exception {
@Test
public void testConnectWithToken() throws Exception {

OAuth2ClientContextImpl context = new OAuth2ClientContextImpl();
OAuth2ClientContext context = new OAuth2ClientContext();
OAuth2ClientContextHolder.setContext(context);

ClientCredentialsResourceDetails resource = new ClientCredentialsResourceDetails();
Expand All @@ -79,7 +80,7 @@ public void testConnectWithToken() throws Exception {
resource.setScope(Arrays.asList("trust"));

ClientCredentialsAccessTokenProvider provider = new ClientCredentialsAccessTokenProvider();
OAuth2AccessToken accessToken = provider.obtainNewAccessToken(resource);
OAuth2AccessToken accessToken = provider.obtainNewAccessToken(resource, new AccessTokenRequest());
context.setAccessTokens(Collections.singletonMap(resource.getId(), accessToken));

// TODO: should this work? The client id is different.
Expand All @@ -105,22 +106,22 @@ public void testConnectWithAutomaticToken() throws Exception {
public void testAttemptedTokenAcquisitionWithNoContext() throws Exception {
AuthorizationCodeAccessTokenProvider provider = new AuthorizationCodeAccessTokenProvider();
try {
OAuth2AccessToken token = provider.obtainNewAccessToken(resource);
OAuth2AccessToken token = provider.obtainNewAccessToken(resource, new AccessTokenRequest());
fail("Expected IllegalStateException");
assertNotNull(token);
} catch (IllegalStateException e) {
String message = e.getMessage();
assertTrue("Wrong message: " + message,
message.contains("No OAuth 2 security context has been established"));
message.contains("No redirect URI has been established"));
}
}

@Test
public void testAttemptedTokenAcquisitionWithWrongContext() throws Exception {
OAuth2ClientContextHolder.setContext(new OAuth2ClientContextImpl());
OAuth2ClientContextHolder.setContext(new OAuth2ClientContext());
AuthorizationCodeAccessTokenProvider provider = new AuthorizationCodeAccessTokenProvider();
try {
OAuth2AccessToken token = provider.obtainNewAccessToken(resource);
OAuth2AccessToken token = provider.obtainNewAccessToken(resource, new AccessTokenRequest());
fail("Expected IllegalStateException");
assertNotNull(token);
} catch (IllegalStateException e) {
Expand Down Expand Up @@ -148,14 +149,15 @@ public void testTokenAcquisitionWithCorrectContext() throws Exception {
resource.setPreEstablishedRedirectUri("http://anywhere");
resource.setState("foo");

OAuth2ClientContextImpl context = new OAuth2ClientContextImpl();
OAuth2ClientContext context = new OAuth2ClientContext();
OAuth2ClientContextHolder.setContext(context);
AuthorizationCodeAccessTokenProvider provider = new AuthorizationCodeAccessTokenProvider();

Map<String, String> requestParams = new HashMap<String, String>();
String uri = null;
AccessTokenRequest accessTokenRequest = new AccessTokenRequest();
try {
OAuth2AccessToken token = provider.obtainNewAccessToken(resource);
OAuth2AccessToken token = provider.obtainNewAccessToken(resource, accessTokenRequest);
fail("Expected UserRedirectRequiredException");
assertNotNull(token);
} catch (UserRedirectRequiredException e) {
Expand All @@ -178,7 +180,7 @@ public void testTokenAcquisitionWithCorrectContext() throws Exception {
.append(URLEncoder.encode(param.getValue(), "UTF-8"));
appendChar = '&';
}
assertEquals(HttpStatus.FOUND, serverRunning.getStatusCode(builder.toString(), headers));
assertEquals(HttpStatus.OK, serverRunning.getStatusCode(builder.toString(), headers));

form = new LinkedMultiValueMap<String, String>();
form.add("user_oauth_approval", "true");
Expand All @@ -194,15 +196,15 @@ public void testTokenAcquisitionWithCorrectContext() throws Exception {
assertNotNull(code);

// Now the access token can be retrieved...
context.setAuthorizationCode(code);
accessTokenRequest.setAuthorizationCode(code);
// TODO: unhack the state (should be autogenerated)
context.setPreservedState("foo");
OAuth2AccessToken token = provider.obtainNewAccessToken(resource);
accessTokenRequest.setPreservedState("foo");
OAuth2AccessToken token = provider.obtainNewAccessToken(resource, accessTokenRequest);
assertNotNull(token);

}

public String extractParameter(String location, String key) {
private String extractParameter(String location, String key) {
location = location.substring(location.indexOf("?") + 1);
for (String query : location.split("&")) {
String[] keyValue = query.split("=");
Expand Down
@@ -1,58 +1,25 @@
package org.springframework.security.oauth2.client.context;

import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
import org.springframework.security.oauth2.common.OAuth2AccessToken;

import java.util.Map;

import org.springframework.security.oauth2.common.OAuth2AccessToken;

/**
* The OAuth 2 security context (for a specific user).
*
* @author Ryan Heaton
* @author Dave Syer
*/
public interface OAuth2ClientContext {

/**
* Get the access tokens for the current context.
*
* @return The access tokens for the current context. The key to the map is the {@link OAuth2ProtectedResourceDetails#getId() id of the protected resource}
* for which the access token is valid.
*/
Map<String, OAuth2AccessToken> getAccessTokens();

/**
* Get the state that has been preserved for the current context.
*
* @return the state that has been preserved for the current context.
*/
Object getPreservedState();
public class OAuth2ClientContext {

/**
* The URI to which a user is to be redirected after authorizing an access token request for this context.
*
* @return The URI to which a user is to be redirected after authorizing an access token request for this context.
*/
String getUserAuthorizationRedirectUri();
private Map<String, OAuth2AccessToken> accessTokens;

/**
* The authorization code for this context.
*
* @return The authorization code, or null if none.
*/
// TODO: this is an implementation detail (only for authorization code grant types)?
String getAuthorizationCode();
public Map<String, OAuth2AccessToken> getAccessTokens() {
return accessTokens;
}

/**
* Any details for this security this context.
*
* @return Any details for this security context.
*/
Object getDetails();
public void setAccessTokens(Map<String, OAuth2AccessToken> accessTokens) {
this.accessTokens = accessTokens;
}

/**
* The error parameters associated with this context.
*
* @return The error parameters associated with this context.
*/
Map<String, String> getErrorParameters();
}

0 comments on commit 177545c

Please sign in to comment.