1515 */
1616package com .stormpath .sdk .servlet .event ;
1717
18+ import com .stormpath .sdk .application .Application ;
1819import com .stormpath .sdk .client .Client ;
1920import com .stormpath .sdk .impl .ds .InternalDataStore ;
21+ import com .stormpath .sdk .impl .error .DefaultError ;
22+ import com .stormpath .sdk .lang .Strings ;
2023import com .stormpath .sdk .oauth .AccessToken ;
24+ import com .stormpath .sdk .oauth .OAuthRequests ;
25+ import com .stormpath .sdk .oauth .OAuthRevocationRequest ;
26+ import com .stormpath .sdk .oauth .OAuthRevocationRequestBuilder ;
27+ import com .stormpath .sdk .oauth .OAuthTokenRevocators ;
2128import com .stormpath .sdk .oauth .RefreshToken ;
29+ import com .stormpath .sdk .oauth .TokenTypeHint ;
2230import com .stormpath .sdk .resource .ResourceException ;
2331import com .stormpath .sdk .servlet .account .event .RegisteredAccountRequestEvent ;
2432import com .stormpath .sdk .servlet .account .event .VerifiedAccountRequestEvent ;
33+ import com .stormpath .sdk .servlet .application .ApplicationResolver ;
2534import com .stormpath .sdk .servlet .authc .FailedAuthenticationRequestEvent ;
2635import com .stormpath .sdk .servlet .authc .LogoutRequestEvent ;
2736import com .stormpath .sdk .servlet .authc .SuccessfulAuthenticationRequestEvent ;
2837import com .stormpath .sdk .servlet .client .ClientResolver ;
38+ import com .stormpath .sdk .servlet .filter .oauth .OAuthErrorCode ;
39+ import com .stormpath .sdk .servlet .filter .oauth .OAuthException ;
2940import com .stormpath .sdk .servlet .http .CookieResolver ;
3041import com .stormpath .sdk .servlet .oauth .impl .JwtTokenSigningKeyResolver ;
3142import io .jsonwebtoken .Claims ;
3748import org .slf4j .Logger ;
3849import org .slf4j .LoggerFactory ;
3950
51+ import javax .servlet .http .HttpServletRequest ;
4052import java .security .Key ;
4153import java .util .LinkedHashMap ;
4254import java .util .Map ;
@@ -51,9 +63,7 @@ public class TokenRevocationRequestEventListener implements RequestEventListener
5163 private final TokenExtractor tokenExtractor = new BearerHeaderTokenExtractor ();
5264 private final CookieResolver accessTokenCookieResolver = new CookieResolver ("access_token" );
5365
54- private final JwtTokenSigningKeyResolver jwtTokenSigningKeyResolver = new JwtTokenSigningKeyResolver ();
55-
56- private Client client = null ;
66+ protected ApplicationResolver applicationResolver = ApplicationResolver .INSTANCE ;
5767
5868 @ Override
5969 public void on (SuccessfulAuthenticationRequestEvent event ) {
@@ -78,30 +88,17 @@ public void on(VerifiedAccountRequestEvent event) {
7888 @ Override
7989 public void on (LogoutRequestEvent event ) {
8090 String jwt = getJwtFromLogoutRequestEvent (event );
81- if (jwt != null ) {
82- if (this .client == null ) {
83- this .client = ClientResolver .INSTANCE .getClient (event .getRequest ()); //will throw if not found
84- }
85-
86- Key signingKey = jwtTokenSigningKeyResolver .getSigningKey (event .getRequest (), event .getResponse (), null , SignatureAlgorithm .HS256 );
87- JwsHeader header = Jwts .parser ().setSigningKey (signingKey .getEncoded ()).parseClaimsJws (jwt ).getHeader ();
88- Claims claims = Jwts .parser ().setSigningKey (signingKey .getEncoded ()).parseClaimsJws (jwt ).getBody ();
89-
90- //Let's be sure this jwt is actually an access token otherwise we will have an error when trying to retrieve
91- //a resource (in order to delete it) that actually is not what we expect
92- if (isAccessToken (header )) {
93- gracefullyDeleteRefreshToken ((String ) claims .get ("rti" ));
94- gracefullyDeleteAccessToken (claims .getId ());
91+ HttpServletRequest request = event .getRequest ();
92+ Application application = applicationResolver .getApplication (request );
93+ if (application != null && jwt != null ) {
94+ try {
95+ OAuthRevocationRequest revocationRequest = OAuthRequests .OAUTH_TOKEN_REVOCATION_REQUEST .builder ().setToken (jwt ).build ();
96+ OAuthTokenRevocators .OAUTH_TOKEN_REVOCATOR .forApplication (application ).revoke (revocationRequest );
97+ } catch (ResourceException e ) {
98+ com .stormpath .sdk .error .Error error = e .getStormpathError ();
99+ String message = error .getMessage ();
100+ log .warn ("There was an error trying to revoke a token" , message );
95101 }
96- //There should never be a refresh token here. Therefore we will not even try to identify if the received JWT is
97- //a refresh token. That would be a bug in the filter chain as a refresh token should never be used to anything other than
98- //obtaining a new access token
99-
100- //Fix for https://github.com/stormpath/stormpath-sdk-java/issues/611
101- log .debug (
102- "The current access and refresh tokens for '{}' have been revoked." ,
103- (event .getAccount () != null ) ? event .getAccount ().getEmail () : "unknown user"
104- );
105102 }
106103 }
107104
@@ -117,34 +114,4 @@ protected String getJwtFromLogoutRequestEvent(LogoutRequestEvent event) {
117114 return jwt ;
118115 }
119116
120- private boolean isAccessToken (JwsHeader header ) {
121- return header .get ("stt" ).equals ("access" );
122- }
123-
124- private void gracefullyDeleteAccessToken (String accessTokenId ) {
125- try {
126- String href = "/accessTokens/" + accessTokenId ;
127- Map <String , Object > map = new LinkedHashMap <String , Object >();
128- map .put ("href" , href );
129- AccessToken accessToken = ((InternalDataStore )client .getDataStore ()).instantiate (AccessToken .class , map , true );
130- accessToken .delete ();
131- } catch (ResourceException e ) {
132- //Let's prevent an error to allow the flow to continue
133- log .warn ("There was an error trying to delete access token with ID {}" , accessTokenId , e );
134- }
135- }
136-
137- private void gracefullyDeleteRefreshToken (String refreshTokenId ) {
138- try {
139- String href = "/refreshTokens/" + refreshTokenId ;
140- Map <String , Object > map = new LinkedHashMap <String , Object >();
141- map .put ("href" , href );
142- RefreshToken refreshToken = ((InternalDataStore )client .getDataStore ()).instantiate (RefreshToken .class , map , true );
143- refreshToken .delete ();
144- } catch (ResourceException e ) {
145- //Let's prevent an error to allow the flow to continue, this component is basically a listener that tries to delete
146- //the current access and refresh tokens on logout, we will only post this error in the log
147- log .warn ("There was an error trying to delete refresh token with ID {}" , refreshTokenId , e );
148- }
149- }
150117}
0 commit comments