Skip to content
This repository was archived by the owner on Sep 28, 2022. It is now read-only.

Commit 150cdfa

Browse files
author
Dominik František Bučík
authored
Merge pull request #64 from dBucik/readTokenAuthMethod
feat: 🎸 Sync Token endpoint authN method
2 parents 0d94dc8 + a06ae5a commit 150cdfa

File tree

3 files changed

+137
-62
lines changed

3 files changed

+137
-62
lines changed

src/main/java/cz/muni/ics/oidc/ToOidcSynchronizer.java

Lines changed: 115 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ public class ToOidcSynchronizer {
9393
public static final String PKCE_TYPE_NONE = "none";
9494
public static final String PKCE_TYPE_PLAIN = "plain code challenge";
9595
public static final String PKCE_TYPE_SHA256 = "SHA256 code challenge";
96-
9796
private final PerunAdapter perunAdapter;
9897
private final String proxyIdentifier;
9998
private final String proxyIdentifierValue;
@@ -152,7 +151,8 @@ public SyncResult syncToOidc(boolean interactiveMode) {
152151
log.info("Removing old clients");
153152
deleteClients(foundClientIds, res);
154153
} else {
155-
log.warn("Script has disabled removing of old clients. This might be due to Peruns unreachability! Check previous logs for more info.");
154+
log.warn("Script has disabled removing of old clients. " +
155+
"This might be due to Peruns unreachability! Check previous logs for more info.");
156156
}
157157
return res;
158158
}
@@ -242,7 +242,9 @@ private void createClient(Map<String, PerunAttributeValue> attrs, SyncResult res
242242
}
243243
}
244244

245-
private void updateClient(MitreidClient original, Map<String, PerunAttributeValue> attrs, SyncResult res)
245+
private void updateClient(MitreidClient original,
246+
Map<String, PerunAttributeValue> attrs,
247+
SyncResult res)
246248
throws BadPaddingException, InvalidKeyException, IllegalBlockSizeException
247249
{
248250
if (actionsProperties.getToOidc().isUpdate()) {
@@ -329,69 +331,82 @@ private void deleteClients(Set<String> foundClientIds, SyncResult res) {
329331
}
330332
}
331333
} else {
332-
log.warn("Deleting of clients is disabled. Following clientIDs would be deleted: {}", clientsToDelete);
334+
log.warn("Deleting of clients is disabled. Following clientIDs would be deleted: {}",
335+
clientsToDelete);
333336
}
334337
}
335338

336339
private void setClientFields(MitreidClient c, Map<String, PerunAttributeValue> attrs)
337340
throws BadPaddingException, InvalidKeyException, IllegalBlockSizeException
338341
{
339-
c.setClientId(attrs.get(perunAttrNames.getClientId()).valueAsString());
340-
c.setClientSecret(Utils.decrypt(
341-
attrs.get(perunAttrNames.getClientSecret()).valueAsString(), cipher, secretKeySpec));
342-
c.setClientName(attrs.get(perunAttrNames.getName()).valueAsMap().get("en"));
343-
c.setClientDescription(attrs.get(perunAttrNames.getDescription()).valueAsMap().get("en"));
344-
c.setRedirectUris(new HashSet<>(attrs.get(perunAttrNames.getRedirectUris()).valueAsList()));
345-
c.setAllowIntrospection(attrs.get(perunAttrNames.getIntrospection()).valueAsBoolean());
346-
c.setPostLogoutRedirectUris(new HashSet<>(attrs.get(perunAttrNames.getPostLogoutRedirectUris()).valueAsList()));
347-
c.setScope(new HashSet<>(attrs.get(perunAttrNames.getScopes()).valueAsList()));
348-
setPolicyUri(c, attrs);
349-
setContacts(c, attrs);
350-
setClientUri(c, attrs);
342+
setClientId(c, attrs);
343+
setClientSecret(c, attrs);
344+
setClientName(c, attrs);
345+
setClientDescription(c, attrs);
346+
setRedirectUris(c, attrs);
347+
setIntrospection(c, attrs);
348+
setPostLogoutRedirectUris(c, attrs);
349+
setScopes(c, attrs);
351350
setGrantAndResponseTypes(c, attrs);
351+
setPKCEOptions(c, attrs);
352+
setTokenEndpointAuthentication(c, attrs);
352353
setRefreshTokens(c, attrs);
353354
setTokenTimeouts(c, attrs);
355+
setPolicyUri(c, attrs);
356+
setContacts(c, attrs);
357+
setClientUri(c, attrs);
354358
}
355359

356-
private void setRefreshTokens(MitreidClient c, Map<String, PerunAttributeValue> attrs) {
357-
Set<String> grantTypes = c.getGrantTypes();
358-
if (grantTypes == null) {
359-
grantTypes = new HashSet<>();
360-
}
361-
if (grantAllowsRefreshTokens(grantTypes)) {
362-
boolean requestedViaAttr = attrs.containsKey(perunAttrNames.getIssueRefreshTokens())
363-
&& attrs.get(perunAttrNames.getIssueRefreshTokens()).valueAsBoolean();
364-
boolean requestedViaScopes = c.getScope().contains(OFFLINE_ACCESS);
365-
log.debug("Refresh tokens requested via: attr({}), scopes({})", requestedViaAttr, requestedViaScopes);
366-
if (requestedViaAttr || requestedViaScopes) {
367-
setUpRefreshTokens(c, attrs);
368-
}
369-
}
360+
private void setClientId(MitreidClient c, Map<String, PerunAttributeValue> attrs) {
361+
String clientId = attrs.get(perunAttrNames.getClientId()).valueAsString();
362+
c.setClientId(clientId);
370363
}
371364

372-
private void setUpRefreshTokens(MitreidClient c, Map<String, PerunAttributeValue> attrs) {
373-
c.getScope().add(OFFLINE_ACCESS);
374-
c.getGrantTypes().add(GRANT_REFRESH_TOKEN);
375-
c.setClearAccessTokensOnRefresh(true);
376-
c.setReuseRefreshToken(false);
377-
PerunAttributeValue reuseTokens = attrs.getOrDefault(perunAttrNames.getReuseRefreshTokens(), null);
378-
if (reuseTokens != null) {
379-
c.setReuseRefreshToken(reuseTokens.valueAsBoolean());
380-
}
365+
private void setClientSecret(MitreidClient c, Map<String, PerunAttributeValue> attrs)
366+
throws IllegalBlockSizeException, BadPaddingException, InvalidKeyException
367+
{
368+
String encryptedClientSecret = attrs.get(perunAttrNames.getClientSecret()).valueAsString();
369+
String clientSecret = Utils.decrypt(encryptedClientSecret, cipher, secretKeySpec);
370+
c.setClientSecret(clientSecret);
381371
}
382372

383-
private boolean grantAllowsRefreshTokens(Set<String> grantTypes) {
384-
boolean res = !grantTypes.isEmpty()
385-
&& (grantTypes.contains(GRANT_DEVICE)
386-
|| grantTypes.contains(GRANT_AUTHORIZATION_CODE)
387-
|| grantTypes.contains(GRANT_HYBRID));
388-
log.debug("Grants '{}' {} issuing refresh tokens", grantTypes, res ? "allow" : "disallow");
389-
return res;
373+
private void setClientName(MitreidClient c, Map<String, PerunAttributeValue> attrs) {
374+
String clientName = attrs.get(perunAttrNames.getName()).valueAsMap().get("en");
375+
c.setClientName(clientName);
376+
}
377+
378+
private void setClientDescription(MitreidClient c, Map<String, PerunAttributeValue> attrs) {
379+
String clientDescription = attrs.get(perunAttrNames.getDescription()).valueAsMap().get("en");
380+
c.setClientDescription(clientDescription);
381+
}
382+
383+
private void setRedirectUris(MitreidClient c, Map<String, PerunAttributeValue> attrs) {
384+
Set<String> redirectUris = new HashSet<>(
385+
attrs.get(perunAttrNames.getRedirectUris()).valueAsList());
386+
c.setRedirectUris(redirectUris);
387+
}
388+
389+
private void setIntrospection(MitreidClient c, Map<String, PerunAttributeValue> attrs) {
390+
boolean introspectionAllowed = attrs.get(perunAttrNames.getIntrospection()).valueAsBoolean();
391+
c.setAllowIntrospection(introspectionAllowed);
392+
}
393+
394+
private void setPostLogoutRedirectUris(MitreidClient c,
395+
Map<String, PerunAttributeValue> attrs)
396+
{
397+
Set<String> postLogoutRedirectUris = new HashSet<>(
398+
attrs.get(perunAttrNames.getPostLogoutRedirectUris()).valueAsList());
399+
c.setPostLogoutRedirectUris(postLogoutRedirectUris);
400+
}
401+
402+
private void setScopes(MitreidClient c, Map<String, PerunAttributeValue> attrs) {
403+
Set<String> scopes = new HashSet<>(attrs.get(perunAttrNames.getScopes()).valueAsList());
404+
c.setScope(scopes);
390405
}
391406

392407
private void setGrantAndResponseTypes(MitreidClient c, Map<String, PerunAttributeValue> attrs) {
393408
List<String> grantTypesAttrValue = attrs.get(perunAttrNames.getGrantTypes()).valueAsList().stream()
394-
.map(String::toLowerCase).collect(Collectors.toList());
409+
.map(String::toLowerCase).collect(Collectors.toList());
395410

396411
Set<String> grantTypes = new HashSet<>();
397412
Set<String> responseTypes = new HashSet<>();
@@ -413,20 +428,14 @@ private void setGrantAndResponseTypes(MitreidClient c, Map<String, PerunAttribut
413428
grantTypes.add(GRANT_AUTHORIZATION_CODE);
414429
responseTypes.addAll(Arrays.asList(RESPONSE_TYPE_HYBRID));
415430
log.debug("Added grants '{} {}' with response types '{}'", GRANT_HYBRID, GRANT_AUTHORIZATION_CODE,
416-
RESPONSE_TYPE_HYBRID);
431+
RESPONSE_TYPE_HYBRID);
417432
}
418433

419434
if (grantTypesAttrValue.contains(DEVICE)) {
420435
grantTypes.add(GRANT_DEVICE);
421436
log.debug("Added grant '{}'", GRANT_DEVICE);
422437
}
423438

424-
if (grantTypes.contains(GRANT_AUTHORIZATION_CODE)
425-
|| grantTypes.contains(GRANT_DEVICE))
426-
{
427-
setPKCEOptions(c, attrs);
428-
}
429-
430439
c.setGrantTypes(grantTypes);
431440
c.setResponseTypes(responseTypes);
432441
}
@@ -439,19 +448,66 @@ private void setPKCEOptions(MitreidClient c, Map<String, PerunAttributeValue> at
439448
log.debug("Code challenge requested is not equal to '{}'", PKCE_TYPE_NONE);
440449
if (PKCE_TYPE_PLAIN.equalsIgnoreCase(codeChallengeType)) {
441450
log.debug("Preparing for PKCE with challenge '{}'", PKCE_TYPE_PLAIN);
442-
preparePkce(c);
443451
c.setCodeChallengeMethod(PKCEAlgorithm.plain);
444452
} else if (PKCE_TYPE_SHA256.equalsIgnoreCase(codeChallengeType)) {
445453
log.debug("Preparing for PKCE with challenge '{}'", PKCE_TYPE_SHA256);
446-
preparePkce(c);
447454
c.setCodeChallengeMethod(PKCEAlgorithm.S256);
448455
}
449456
}
450457
}
451458

452-
private void preparePkce(MitreidClient c) {
453-
c.setClientSecret(null);
454-
c.setTokenEndpointAuthMethod(MitreidClient.AuthMethod.NONE);
459+
private void setTokenEndpointAuthentication(MitreidClient c,
460+
Map<String, PerunAttributeValue> attrs)
461+
{
462+
String authMethodAttrValue = attrs.get(perunAttrNames.getTokenEndpointAuthenticationMethod())
463+
.valueAsString();
464+
MitreidClient.AuthMethod authMethod = MitreidClient.AuthMethod.getByValue(authMethodAttrValue);
465+
if (authMethod == null) {
466+
log.debug("Failed to parse token endpoint authentication method." +
467+
" Using client_secret_basic as default value.");
468+
authMethod = MitreidClient.AuthMethod.SECRET_BASIC;
469+
}
470+
c.setTokenEndpointAuthMethod(authMethod);
471+
if (MitreidClient.AuthMethod.NONE.equals(authMethod)) {
472+
log.debug("NONE used as token endpoint authentication method. Removing client_secret");
473+
c.setClientSecret(null);
474+
}
475+
}
476+
477+
private void setRefreshTokens(MitreidClient c, Map<String, PerunAttributeValue> attrs) {
478+
Set<String> grantTypes = c.getGrantTypes();
479+
if (grantTypes == null) {
480+
grantTypes = new HashSet<>();
481+
}
482+
if (grantAllowsRefreshTokens(grantTypes)) {
483+
boolean requestedViaAttr = attrs.containsKey(perunAttrNames.getIssueRefreshTokens())
484+
&& attrs.get(perunAttrNames.getIssueRefreshTokens()).valueAsBoolean();
485+
boolean requestedViaScopes = c.getScope().contains(OFFLINE_ACCESS);
486+
log.debug("Refresh tokens requested via: attr({}), scopes({})", requestedViaAttr, requestedViaScopes);
487+
if (requestedViaAttr || requestedViaScopes) {
488+
setUpRefreshTokens(c, attrs);
489+
}
490+
}
491+
}
492+
493+
private void setUpRefreshTokens(MitreidClient c, Map<String, PerunAttributeValue> attrs) {
494+
c.getScope().add(OFFLINE_ACCESS);
495+
c.getGrantTypes().add(GRANT_REFRESH_TOKEN);
496+
c.setClearAccessTokensOnRefresh(true);
497+
c.setReuseRefreshToken(false);
498+
PerunAttributeValue reuseTokens = attrs.getOrDefault(perunAttrNames.getReuseRefreshTokens(), null);
499+
if (reuseTokens != null) {
500+
c.setReuseRefreshToken(reuseTokens.valueAsBoolean());
501+
}
502+
}
503+
504+
private boolean grantAllowsRefreshTokens(Set<String> grantTypes) {
505+
boolean res = !grantTypes.isEmpty()
506+
&& (grantTypes.contains(GRANT_DEVICE)
507+
|| grantTypes.contains(GRANT_AUTHORIZATION_CODE)
508+
|| grantTypes.contains(GRANT_HYBRID));
509+
log.debug("Grants '{}' {} issuing refresh tokens", grantTypes, res ? "allow" : "disallow");
510+
return res;
455511
}
456512

457513
private void setTokenTimeouts(MitreidClient c, Map<String, PerunAttributeValue> attrs) {

src/main/java/cz/muni/ics/oidc/props/AttrsMapping.java

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ public class AttrsMapping {
4444
@NotBlank private String introspection;
4545
@NotBlank private String postLogoutRedirectUris;
4646
@NotBlank private String issueRefreshTokens;
47+
48+
@NotBlank private String tokenEndpointAuthenticationMethod;
4749
private List<String> homePageUris;
4850
private String tokenTimeouts;
4951
private String reuseRefreshTokens;
@@ -57,9 +59,25 @@ public class AttrsMapping {
5759

5860
public List<String> getNames() {
5961
List<String> attrNames = new ArrayList<>(
60-
Arrays.asList(clientId, clientSecret, name, description, redirectUris, privacyPolicy, scopes,
61-
grantTypes, codeChallengeType, introspection, postLogoutRedirectUris, issueRefreshTokens,
62-
masterProxyIdentifier, proxyIdentifier, isTestSp, isOidc, managersGroupId)
62+
Arrays.asList(clientId,
63+
clientSecret,
64+
name,
65+
description,
66+
redirectUris,
67+
privacyPolicy,
68+
scopes,
69+
grantTypes,
70+
codeChallengeType,
71+
introspection,
72+
postLogoutRedirectUris,
73+
issueRefreshTokens,
74+
tokenEndpointAuthenticationMethod,
75+
masterProxyIdentifier,
76+
proxyIdentifier,
77+
isTestSp,
78+
isOidc,
79+
managersGroupId
80+
)
6381
);
6482
attrNames.addAll(contacts);
6583

src/main/resources/application.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ attributes:
2727
contacts:
2828
- "urn:perun:facility:attribute-def:def:administratorContact"
2929
scopes: "urn:perun:facility:attribute-def:def:requiredScopes"
30+
token_endpoint_authentication_method: "urn:perun:facility:attribute-def:def:OIDCTokenEndpointAuthenticationMethod"
3031
grant_types: "urn:perun:facility:attribute-def:def:OIDCGrantTypes"
3132
code_challenge_type: "urn:perun:facility:attribute-def:def:OIDCCodeChallengeType"
3233
introspection: "urn:perun:facility:attribute-def:def:OIDCAllowIntrospection"

0 commit comments

Comments
 (0)