16
16
*******************************************************************************/
17
17
package org .mitre .oauth2 .web ;
18
18
19
- import java . security . Principal ;
19
+ import static org . mitre . oauth2 . web . AuthenticationUtilities . ensureOAuthScope ;
20
20
21
+ import java .util .Collection ;
22
+
23
+ import org .mitre .oauth2 .model .ClientDetailsEntity ;
21
24
import org .mitre .oauth2 .model .OAuth2AccessTokenEntity ;
22
25
import org .mitre .oauth2 .model .OAuth2RefreshTokenEntity ;
26
+ import org .mitre .oauth2 .service .ClientDetailsEntityService ;
23
27
import org .mitre .oauth2 .service .OAuth2TokenEntityService ;
28
+ import org .mitre .oauth2 .service .SystemScopeService ;
24
29
import org .mitre .openid .connect .view .HttpCodeView ;
30
+ import org .mitre .uma .model .ResourceSet ;
25
31
import org .slf4j .Logger ;
26
32
import org .slf4j .LoggerFactory ;
27
33
import org .springframework .beans .factory .annotation .Autowired ;
28
34
import org .springframework .http .HttpStatus ;
29
35
import org .springframework .security .access .prepost .PreAuthorize ;
36
+ import org .springframework .security .core .Authentication ;
30
37
import org .springframework .security .oauth2 .common .exceptions .InvalidTokenException ;
31
38
import org .springframework .security .oauth2 .provider .OAuth2Authentication ;
32
39
import org .springframework .security .oauth2 .provider .OAuth2Request ;
38
45
@ Controller
39
46
public class RevocationEndpoint {
40
47
@ Autowired
41
- OAuth2TokenEntityService tokenServices ;
48
+ private ClientDetailsEntityService clientService ;
49
+
50
+ @ Autowired
51
+ private OAuth2TokenEntityService tokenServices ;
42
52
43
53
/**
44
54
* Logger for this class
@@ -49,32 +59,53 @@ public class RevocationEndpoint {
49
59
50
60
@ PreAuthorize ("hasRole('ROLE_ADMIN') or hasRole('ROLE_CLIENT')" )
51
61
@ RequestMapping ("/" + URL )
52
- public String revoke (@ RequestParam ("token" ) String tokenValue , @ RequestParam (value = "token_type_hint" , required = false ) String tokenType , Principal principal , Model model ) {
62
+ public String revoke (@ RequestParam ("token" ) String tokenValue , @ RequestParam (value = "token_type_hint" , required = false ) String tokenType , Authentication auth , Model model ) {
53
63
54
64
// This is the token as passed in from OAuth (in case we need it some day)
55
65
//OAuth2AccessTokenEntity tok = tokenServices.getAccessToken((OAuth2Authentication) principal);
56
66
57
- OAuth2Request authRequest = null ;
58
- if (principal instanceof OAuth2Authentication ) {
59
- // if the client is acting on its own behalf (the common case), pull out the client authorization request
60
- authRequest = ((OAuth2Authentication ) principal ).getOAuth2Request ();
67
+ ClientDetailsEntity authClient = null ;
68
+
69
+ if (auth instanceof OAuth2Authentication ) {
70
+ // the client authenticated with OAuth, do our UMA checks
71
+ ensureOAuthScope (auth , SystemScopeService .UMA_PROTECTION_SCOPE );
72
+ // get out the client that was issued the access token (not the token being revoked)
73
+ OAuth2Authentication o2a = (OAuth2Authentication ) auth ;
74
+
75
+ String authClientId = o2a .getOAuth2Request ().getClientId ();
76
+ authClient = clientService .loadClientByClientId (authClientId );
77
+
78
+ // the owner is the user who authorized the token in the first place
79
+ String ownerId = o2a .getUserAuthentication ().getName ();
80
+
81
+ } else {
82
+ // the client authenticated directly, make sure it's got the right access
83
+
84
+ String authClientId = auth .getName (); // direct authentication puts the client_id into the authentication's name field
85
+ authClient = clientService .loadClientByClientId (authClientId );
86
+
61
87
}
62
88
63
89
try {
64
90
// check and handle access tokens first
65
91
66
92
OAuth2AccessTokenEntity accessToken = tokenServices .readAccessToken (tokenValue );
67
- if (authRequest != null ) {
68
- // client acting on its own, make sure it owns the token
69
- if (!accessToken .getClient ().getClientId ().equals (authRequest .getClientId ())) {
70
- // trying to revoke a token we don't own, throw a 403
71
- model .addAttribute (HttpCodeView .CODE , HttpStatus .FORBIDDEN );
72
- return HttpCodeView .VIEWNAME ;
73
- }
93
+
94
+ // client acting on its own, make sure it owns the token
95
+ if (!accessToken .getClient ().getClientId ().equals (authClient .getClientId ())) {
96
+ // trying to revoke a token we don't own, throw a 403
97
+
98
+ logger .info ("Client " + authClient .getClientId () + " tried to revoke a token owned by " + accessToken .getClient ().getClientId ());
99
+
100
+ model .addAttribute (HttpCodeView .CODE , HttpStatus .FORBIDDEN );
101
+ return HttpCodeView .VIEWNAME ;
74
102
}
75
103
76
104
// if we got this far, we're allowed to do this
77
105
tokenServices .revokeAccessToken (accessToken );
106
+
107
+ logger .debug ("Client " + authClient .getClientId () + " revoked access token " + tokenValue );
108
+
78
109
model .addAttribute (HttpCodeView .CODE , HttpStatus .OK );
79
110
return HttpCodeView .VIEWNAME ;
80
111
@@ -84,24 +115,30 @@ public String revoke(@RequestParam("token") String tokenValue, @RequestParam(val
84
115
85
116
try {
86
117
OAuth2RefreshTokenEntity refreshToken = tokenServices .getRefreshToken (tokenValue );
87
- if (authRequest != null ) {
88
- // client acting on its own, make sure it owns the token
89
- if (!refreshToken .getClient ().getClientId ().equals (authRequest .getClientId ())) {
90
- // trying to revoke a token we don't own, throw a 403
91
- model .addAttribute (HttpCodeView .CODE , HttpStatus .FORBIDDEN );
92
- return HttpCodeView .VIEWNAME ;
93
- }
118
+ // client acting on its own, make sure it owns the token
119
+ if (!refreshToken .getClient ().getClientId ().equals (authClient .getClientId ())) {
120
+ // trying to revoke a token we don't own, throw a 403
121
+
122
+ logger .info ("Client " + authClient .getClientId () + " tried to revoke a token owned by " + refreshToken .getClient ().getClientId ());
123
+
124
+ model .addAttribute (HttpCodeView .CODE , HttpStatus .FORBIDDEN );
125
+ return HttpCodeView .VIEWNAME ;
94
126
}
95
127
96
128
// if we got this far, we're allowed to do this
97
129
tokenServices .revokeRefreshToken (refreshToken );
130
+
131
+ logger .debug ("Client " + authClient .getClientId () + " revoked access token " + tokenValue );
132
+
98
133
model .addAttribute (HttpCodeView .CODE , HttpStatus .OK );
99
134
return HttpCodeView .VIEWNAME ;
100
135
101
136
} catch (InvalidTokenException e1 ) {
102
137
103
138
// neither token type was found, simply say "OK" and be on our way.
104
139
140
+ logger .debug ("Failed to revoke token " + tokenValue );
141
+
105
142
model .addAttribute (HttpCodeView .CODE , HttpStatus .OK );
106
143
return HttpCodeView .VIEWNAME ;
107
144
}
0 commit comments