Skip to content

Commit 74ea428

Browse files
committed
added check for HEART mode consistency
1 parent 028265f commit 74ea428

File tree

1 file changed

+103
-2
lines changed

1 file changed

+103
-2
lines changed

openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultOAuth2ClientDetailsEntityService.java

Lines changed: 103 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,12 @@
2828
import java.util.concurrent.TimeUnit;
2929

3030
import org.apache.commons.codec.binary.Base64;
31+
import org.apache.http.MethodNotSupportedException;
3132
import org.apache.http.client.HttpClient;
3233
import org.apache.http.impl.client.HttpClientBuilder;
3334
import org.mitre.oauth2.model.ClientDetailsEntity;
3435
import org.mitre.oauth2.model.SystemScope;
36+
import org.mitre.oauth2.model.ClientDetailsEntity.AuthMethod;
3537
import org.mitre.oauth2.repository.OAuth2ClientRepository;
3638
import org.mitre.oauth2.repository.OAuth2TokenRepository;
3739
import org.mitre.oauth2.service.ClientDetailsEntityService;
@@ -121,12 +123,15 @@ public ClientDetailsEntity saveNewClient(ClientDetailsEntity client) {
121123
if (Strings.isNullOrEmpty(client.getClientId())) {
122124
client = generateClientId(client);
123125
}
124-
126+
125127
// make sure that clients with the "refresh_token" grant type have the "offline_access" scope, and vice versa
126128
ensureRefreshTokenConsistency(client);
127129

128130
// make sure we don't have both a JWKS and a JWKS URI
129131
ensureKeyConsistency(client);
132+
133+
// check consistency when using HEART mode
134+
checkHeartMode(client);
130135

131136
// timestamp this to right now
132137
client.setCreatedAt(new Date());
@@ -146,6 +151,7 @@ public ClientDetailsEntity saveNewClient(ClientDetailsEntity client) {
146151
}
147152

148153
/**
154+
* Make sure the client has only one type of key registered
149155
* @param client
150156
*/
151157
private void ensureKeyConsistency(ClientDetailsEntity client) {
@@ -155,6 +161,9 @@ private void ensureKeyConsistency(ClientDetailsEntity client) {
155161
}
156162
}
157163

164+
/**
165+
* Make sure the client doesn't request any system reserved scopes
166+
*/
158167
private void ensureNoReservedScopes(ClientDetailsEntity client) {
159168
// make sure a client doesn't get any special system scopes
160169
Set<SystemScope> requestedScope = scopeService.fromStrings(client.getScope());
@@ -164,6 +173,10 @@ private void ensureNoReservedScopes(ClientDetailsEntity client) {
164173
client.setScope(scopeService.toStrings(requestedScope));
165174
}
166175

176+
/**
177+
* Load the sector identifier URI if it exists and check the redirect URIs against it
178+
* @param client
179+
*/
167180
private void checkSectorIdentifierUri(ClientDetailsEntity client) {
168181
if (!Strings.isNullOrEmpty(client.getSectorIdentifierUri())) {
169182
try {
@@ -183,6 +196,10 @@ private void checkSectorIdentifierUri(ClientDetailsEntity client) {
183196
}
184197
}
185198

199+
/**
200+
* Make sure the client has the appropriate scope and grant type.
201+
* @param client
202+
*/
186203
private void ensureRefreshTokenConsistency(ClientDetailsEntity client) {
187204
if (client.getAuthorizedGrantTypes().contains("refresh_token")
188205
|| client.getScope().contains(SystemScopeService.OFFLINE_ACCESS)) {
@@ -191,6 +208,82 @@ private void ensureRefreshTokenConsistency(ClientDetailsEntity client) {
191208
}
192209
}
193210

211+
/**
212+
* If HEART mode is enabled, make sure the client meets the requirements:
213+
* - Only one of authorization_code, implicit, or client_credentials can be used at a time
214+
* - A redirect_uri must be registered with either authorization_code or implicit
215+
* - A key must be registered
216+
* - A client secret must not be generated
217+
* - authorization_code and client_credentials must use the private_key authorization method
218+
* @param client
219+
*/
220+
private void checkHeartMode(ClientDetailsEntity client) {
221+
if (config.isHeartMode()) {
222+
if (client.getGrantTypes().contains("authorization_code")) {
223+
// make sure we don't have incompatible grant types
224+
if (client.getGrantTypes().contains("implicit") || client.getGrantTypes().contains("client_credentials")) {
225+
throw new IllegalArgumentException("[HEART mode] Incompatible grant types");
226+
}
227+
228+
// make sure we've got the right authentication method
229+
if (client.getTokenEndpointAuthMethod() == null || client.getTokenEndpointAuthMethod().equals(AuthMethod.PRIVATE_KEY)) {
230+
throw new IllegalArgumentException("[HEART mode] Authorization code clients must use the private_key authentication method");
231+
}
232+
233+
// make sure we've got a redirect URI
234+
if (client.getRedirectUris().isEmpty()) {
235+
throw new IllegalArgumentException("[HEART mode] Authorization code clients must register at least one redirect URI");
236+
}
237+
}
238+
239+
if (client.getGrantTypes().contains("implicit")) {
240+
// make sure we don't have incompatible grant types
241+
if (client.getGrantTypes().contains("authorization_code") || client.getGrantTypes().contains("client_credentials") || client.getGrantTypes().contains("refresh_token")) {
242+
throw new IllegalArgumentException("[HEART mode] Incompatible grant types");
243+
}
244+
245+
// make sure we've got the right authentication method
246+
if (client.getTokenEndpointAuthMethod() == null || client.getTokenEndpointAuthMethod().equals(AuthMethod.NONE)) {
247+
throw new IllegalArgumentException("[HEART mode] Implicit clients must use the none authentication method");
248+
}
249+
250+
// make sure we've got a redirect URI
251+
if (client.getRedirectUris().isEmpty()) {
252+
throw new IllegalArgumentException("[HEART mode] Implicit clients must register at least one redirect URI");
253+
}
254+
}
255+
256+
if (client.getGrantTypes().contains("client_credentials")) {
257+
// make sure we don't have incompatible grant types
258+
if (client.getGrantTypes().contains("authorization_code") || client.getGrantTypes().contains("implicit") || client.getGrantTypes().contains("refresh_token")) {
259+
throw new IllegalArgumentException("[HEART mode] Incompatible grant types");
260+
}
261+
262+
// make sure we've got the right authentication method
263+
if (client.getTokenEndpointAuthMethod() == null || client.getTokenEndpointAuthMethod().equals(AuthMethod.PRIVATE_KEY)) {
264+
throw new IllegalArgumentException("[HEART mode] Client credentials clients must use the private_key authentication method");
265+
}
266+
267+
// make sure we've got a redirect URI
268+
if (!client.getRedirectUris().isEmpty()) {
269+
throw new IllegalArgumentException("[HEART mode] Client credentials clients must not register a redirect URI");
270+
}
271+
272+
}
273+
274+
// make sure we don't have a client secret
275+
if (!Strings.isNullOrEmpty(client.getClientSecret())) {
276+
throw new IllegalArgumentException("[HEART mode] Client secrets are not allowed");
277+
}
278+
279+
// make sure we've got a key registered
280+
if (client.getJwks() == null && Strings.isNullOrEmpty(client.getJwksUri())) {
281+
throw new IllegalArgumentException("[HEART mode] All clients must have a key registered");
282+
}
283+
284+
}
285+
}
286+
194287
/**
195288
* Get the client by its internal ID
196289
*/
@@ -283,6 +376,9 @@ public ClientDetailsEntity updateClient(ClientDetailsEntity oldClient, ClientDet
283376

284377
// make sure we don't have both a JWKS and a JWKS URI
285378
ensureKeyConsistency(newClient);
379+
380+
// check consistency when using HEART mode
381+
checkHeartMode(newClient);
286382

287383
// check the sector URI
288384
checkSectorIdentifierUri(newClient);
@@ -317,7 +413,12 @@ public ClientDetailsEntity generateClientId(ClientDetailsEntity client) {
317413
*/
318414
@Override
319415
public ClientDetailsEntity generateClientSecret(ClientDetailsEntity client) {
320-
client.setClientSecret(Base64.encodeBase64URLSafeString(new BigInteger(512, new SecureRandom()).toByteArray()).replace("=", ""));
416+
if (config.isHeartMode()) {
417+
logger.error("[HEART mode] Can't generate a client secret, skipping step; client won't be saved due to invalid configuration");
418+
client.setClientSecret(null);
419+
} else {
420+
client.setClientSecret(Base64.encodeBase64URLSafeString(new BigInteger(512, new SecureRandom()).toByteArray()).replace("=", ""));
421+
}
321422
return client;
322423
}
323424

0 commit comments

Comments
 (0)