Skip to content

Commit f4740bf

Browse files
aanganesDave Syer
authored andcommitted
Added ImplicitGrantService, mimics the AuthorizationCodeService pattern
AuthorizationCodeService pattern is used by the code flow. This change allows the ImplicitTokenGranter to retrieve the original AuthorizationRequest, using the incoming TokenRequest as a key.
1 parent 7f05a32 commit f4740bf

File tree

7 files changed

+113
-6
lines changed

7 files changed

+113
-6
lines changed

spring-security-oauth2/src/main/java/org/springframework/security/oauth2/config/AuthorizationServerBeanDefinitionParser.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import org.springframework.security.oauth2.provider.endpoint.TokenEndpoint;
3636
import org.springframework.security.oauth2.provider.endpoint.WhitelabelApprovalEndpoint;
3737
import org.springframework.security.oauth2.provider.implicit.ImplicitTokenGranter;
38+
import org.springframework.security.oauth2.provider.implicit.InMemoryImplicitGrantService;
3839
import org.springframework.security.oauth2.provider.password.ResourceOwnerPasswordTokenGranter;
3940
import org.springframework.security.oauth2.provider.refresh.RefreshTokenGranter;
4041
import org.springframework.util.StringUtils;
@@ -65,11 +66,21 @@ protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element, P
6566
String errorPage = element.getAttribute("error-page");
6667
String approvalParameter = element.getAttribute("approval-parameter-name");
6768
String redirectResolverRef = element.getAttribute("redirect-resolver-ref");
69+
70+
String implicitGrantServiceRef = element.getAttribute("implicit-grant-service-ref");
6871

6972
// Create a bean definition speculatively for the auth endpoint
7073
BeanDefinitionBuilder authorizationEndpointBean = BeanDefinitionBuilder
7174
.rootBeanDefinition(AuthorizationEndpoint.class);
7275

76+
if (!StringUtils.hasText(implicitGrantServiceRef)) {
77+
implicitGrantServiceRef = "inMemoryImplicitGrantService";
78+
BeanDefinitionBuilder implicitGrantService = BeanDefinitionBuilder
79+
.rootBeanDefinition(InMemoryImplicitGrantService.class);
80+
parserContext.getRegistry().registerBeanDefinition(implicitGrantServiceRef,
81+
implicitGrantService.getBeanDefinition());
82+
}
83+
7384
if (!StringUtils.hasText(oAuth2RequestFactoryRef)) {
7485
oAuth2RequestFactoryRef = "oAuth2AuthorizationRequestManager";
7586
BeanDefinitionBuilder oAuth2RequestManager = BeanDefinitionBuilder
@@ -78,6 +89,7 @@ protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element, P
7889
parserContext.getRegistry().registerBeanDefinition(oAuth2RequestFactoryRef,
7990
oAuth2RequestManager.getBeanDefinition());
8091
}
92+
authorizationEndpointBean.addPropertyReference("implicitGrantService", implicitGrantServiceRef);
8193

8294
ManagedList<BeanMetadataElement> tokenGranters = null;
8395
if (!StringUtils.hasText(tokenGranterRef)) {
@@ -150,6 +162,13 @@ protected AbstractBeanDefinition parseEndpointAndReturnFilter(Element element, P
150162
if (implicitElement != null && !"true".equalsIgnoreCase(implicitElement.getAttribute("disabled"))) {
151163
BeanDefinitionBuilder implicitGranterBean = BeanDefinitionBuilder
152164
.rootBeanDefinition(ImplicitTokenGranter.class);
165+
166+
String implicitGrantServiceRef2 = implicitElement.getAttribute("implicit-grant-service-ref");
167+
if (!StringUtils.hasText(implicitGrantServiceRef2)) {
168+
implicitGrantServiceRef2 = implicitGrantServiceRef;
169+
}
170+
implicitGranterBean.addPropertyReference("implicitGrantService", implicitGrantServiceRef2);
171+
153172
implicitGranterBean.addConstructorArgReference(tokenServicesRef);
154173
implicitGranterBean.addConstructorArgReference(clientDetailsRef);
155174
implicitGranterBean.addConstructorArgReference(oAuth2RequestFactoryRef);

spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/endpoint/AuthorizationEndpoint.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,18 +40,20 @@
4040
import org.springframework.security.oauth2.common.exceptions.UnsupportedResponseTypeException;
4141
import org.springframework.security.oauth2.common.exceptions.UserDeniedAuthorizationException;
4242
import org.springframework.security.oauth2.common.util.OAuth2Utils;
43+
import org.springframework.security.oauth2.provider.AuthorizationRequest;
4344
import org.springframework.security.oauth2.provider.ClientDetails;
4445
import org.springframework.security.oauth2.provider.ClientRegistrationException;
4546
import org.springframework.security.oauth2.provider.DefaultOAuth2RequestValidator;
4647
import org.springframework.security.oauth2.provider.OAuth2Authentication;
47-
import org.springframework.security.oauth2.provider.AuthorizationRequest;
48-
import org.springframework.security.oauth2.provider.OAuth2RequestValidator;
4948
import org.springframework.security.oauth2.provider.OAuth2Request;
49+
import org.springframework.security.oauth2.provider.OAuth2RequestValidator;
5050
import org.springframework.security.oauth2.provider.TokenRequest;
5151
import org.springframework.security.oauth2.provider.approval.DefaultUserApprovalHandler;
5252
import org.springframework.security.oauth2.provider.approval.UserApprovalHandler;
5353
import org.springframework.security.oauth2.provider.code.AuthorizationCodeServices;
5454
import org.springframework.security.oauth2.provider.code.InMemoryAuthorizationCodeServices;
55+
import org.springframework.security.oauth2.provider.implicit.ImplicitGrantService;
56+
import org.springframework.security.oauth2.provider.implicit.InMemoryImplicitGrantService;
5557
import org.springframework.util.StringUtils;
5658
import org.springframework.web.HttpSessionRequiredException;
5759
import org.springframework.web.bind.annotation.ExceptionHandler;
@@ -99,6 +101,8 @@ public class AuthorizationEndpoint extends AbstractEndpoint implements Initializ
99101
private SessionAttributeStore sessionAttributeStore = new DefaultSessionAttributeStore();
100102

101103
private OAuth2RequestValidator oAuth2RequestValidator = new DefaultOAuth2RequestValidator();
104+
105+
private ImplicitGrantService implicitGrantService = new InMemoryImplicitGrantService();
102106

103107
private String userApprovalPage = "forward:/oauth/confirm_access";
104108

@@ -250,6 +254,8 @@ private ModelAndView getUserApprovalPageResponse(Map<String, Object> model,
250254
private ModelAndView getImplicitGrantResponse(AuthorizationRequest authorizationRequest) {
251255
try {
252256
TokenRequest tokenRequest = getOAuth2RequestFactory().createTokenRequest(authorizationRequest, "implicit");
257+
OAuth2Request storedOAuth2Request = getOAuth2RequestFactory().createOAuth2Request(authorizationRequest);
258+
implicitGrantService.store(storedOAuth2Request, tokenRequest);
253259
OAuth2AccessToken accessToken = getTokenGranter().grant("implicit", tokenRequest);
254260
if (accessToken == null) {
255261
throw new UnsupportedResponseTypeException("Unsupported response type: token");
@@ -446,6 +452,10 @@ public void setUserApprovalHandler(UserApprovalHandler userApprovalHandler) {
446452
public void setoAuth2RequestValidator(OAuth2RequestValidator oAuth2RequestValidator) {
447453
this.oAuth2RequestValidator = oAuth2RequestValidator;
448454
}
455+
456+
public void setImplicitGrantService(ImplicitGrantService implicitGrantService) {
457+
this.implicitGrantService = implicitGrantService;
458+
}
449459

450460
@ExceptionHandler(ClientRegistrationException.class)
451461
public ModelAndView handleClientRegistrationException(Exception e, ServletWebRequest webRequest) throws Exception {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package org.springframework.security.oauth2.provider.implicit;
2+
3+
import org.springframework.security.oauth2.provider.OAuth2Request;
4+
import org.springframework.security.oauth2.provider.TokenRequest;
5+
6+
/**
7+
* Service to associate & store an incoming AuthorizationRequest with the TokenRequest that is passed
8+
* to the ImplicitTokenGranter during the Implicit flow. This mimics the AuthorizationCodeServices
9+
* functionality from the Authorization Code flow, allowing the ImplicitTokenGranter to reference the original
10+
* AuthorizationRequest, while still allowing the ImplicitTokenGranter to adhere to the TokenGranter interface.
11+
*
12+
* @author Amanda Anganes
13+
*
14+
*/
15+
public interface ImplicitGrantService {
16+
17+
/**
18+
* Save an association between an OAuth2Request and a TokenRequest.
19+
*
20+
* @param originalRequest
21+
* @param tokenRequest
22+
*/
23+
public void store(OAuth2Request originalRequest, TokenRequest tokenRequest);
24+
25+
/**
26+
* Look up and return the OAuth2Request associated with the given TokenRequest.
27+
*
28+
* @param tokenRequest
29+
* @return
30+
*/
31+
public OAuth2Request remove(TokenRequest tokenRequest);
32+
33+
}

spring-security-oauth2/src/main/java/org/springframework/security/oauth2/provider/implicit/ImplicitTokenGranter.java

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323
import org.springframework.security.oauth2.provider.ClientDetails;
2424
import org.springframework.security.oauth2.provider.ClientDetailsService;
2525
import org.springframework.security.oauth2.provider.OAuth2Authentication;
26-
import org.springframework.security.oauth2.provider.OAuth2RequestFactory;
2726
import org.springframework.security.oauth2.provider.OAuth2Request;
27+
import org.springframework.security.oauth2.provider.OAuth2RequestFactory;
2828
import org.springframework.security.oauth2.provider.TokenRequest;
2929
import org.springframework.security.oauth2.provider.token.AbstractTokenGranter;
3030
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
@@ -37,6 +37,8 @@ public class ImplicitTokenGranter extends AbstractTokenGranter {
3737

3838
private static final String GRANT_TYPE = "implicit";
3939

40+
private ImplicitGrantService service;
41+
4042
public ImplicitTokenGranter(AuthorizationServerTokenServices tokenServices, ClientDetailsService clientDetailsService, OAuth2RequestFactory requestFactory) {
4143
super(tokenServices, clientDetailsService, requestFactory, GRANT_TYPE);
4244
}
@@ -48,11 +50,15 @@ protected OAuth2Authentication getOAuth2Authentication(ClientDetails client, Tok
4850
if (userAuth==null || !userAuth.isAuthenticated()) {
4951
throw new InsufficientAuthenticationException("There is no currently logged in user");
5052
}
51-
52-
OAuth2Request storedOAuth2Request = getRequestFactory().createOAuth2Request(client, clientToken);
5353

54-
return new OAuth2Authentication(storedOAuth2Request, userAuth);
54+
OAuth2Request requestForStorage = service.remove(clientToken);
55+
56+
return new OAuth2Authentication(requestForStorage, userAuth);
5557

5658
}
59+
60+
public void setImplicitGrantService(ImplicitGrantService service) {
61+
this.service = service;
62+
}
5763

5864
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package org.springframework.security.oauth2.provider.implicit;
2+
3+
import java.util.concurrent.ConcurrentHashMap;
4+
5+
import org.springframework.security.oauth2.provider.OAuth2Request;
6+
import org.springframework.security.oauth2.provider.TokenRequest;
7+
8+
/**
9+
* In-memory implementation of the ImplicitGrantService.
10+
*
11+
* @author Amanda Anganes
12+
*
13+
*/
14+
public class InMemoryImplicitGrantService implements ImplicitGrantService {
15+
16+
protected final ConcurrentHashMap<TokenRequest, OAuth2Request> requestStore = new ConcurrentHashMap<TokenRequest, OAuth2Request>();
17+
18+
public void store(OAuth2Request originalRequest, TokenRequest tokenRequest) {
19+
this.requestStore.put(tokenRequest, originalRequest);
20+
}
21+
22+
public OAuth2Request remove(TokenRequest tokenRequest) {
23+
OAuth2Request request = this.requestStore.remove(tokenRequest);
24+
return request;
25+
}
26+
27+
}

spring-security-oauth2/src/main/resources/org/springframework/security/oauth2/spring-security-oauth2-1.0.xsd

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,15 @@
235235
</xs:annotation>
236236
</xs:attribute>
237237

238+
<xs:attribute name="implicit-grant-service-ref" type="xs:string">
239+
<xs:annotation>
240+
<xs:documentation>
241+
The reference to the bean that defines the
242+
implicit grant service.
243+
</xs:documentation>
244+
</xs:annotation>
245+
</xs:attribute>
246+
238247
<xs:attribute name="token-services-ref" type="xs:string">
239248
<xs:annotation>
240249
<xs:documentation>

spring-security-oauth2/src/test/resources/org/springframework/security/oauth2/config/authorization-server-extras.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
<oauth:authorization-server client-details-service-ref="clientDetails" token-services-ref="tokens"
99
authorization-endpoint-url="/authorize" token-endpoint-url="/token" approval-parameter-name="approve" error-page="/error"
1010
authorization-request-manager-ref="factory" redirect-resolver-ref="resolver" token-granter-ref="granter"
11+
implicit-grant-service-ref="implicitService"
1112
user-approval-handler-ref="approvals" user-approval-page="/approve">
1213
<oauth:authorization-code />
1314
</oauth:authorization-server>
@@ -30,6 +31,8 @@
3031
<constructor-arg ref="clientDetails" />
3132
<constructor-arg ref="factory" />
3233
</bean>
34+
35+
<bean id="implicitService" class="org.springframework.security.oauth2.provider.implicit.InMemoryImplicitGrantService" />
3336

3437
<bean id="approvals" class="org.springframework.security.oauth2.provider.approval.DefaultUserApprovalHandler" />
3538

0 commit comments

Comments
 (0)