Skip to content

Commit

Permalink
Allow empty token endpoint for implicit flow (#45038)
Browse files Browse the repository at this point in the history
When using the implicit flow in OpenID Connect, the
op.token_endpoint_url should not be mandatory as there is no need
to contact the token endpoint of the OP.
  • Loading branch information
jkakavas committed Aug 8, 2019
1 parent ddcc38c commit 99ddb8b
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,10 @@ public class OpenIdConnectProviderConfiguration {
private final String jwkSetPath;

public OpenIdConnectProviderConfiguration(Issuer issuer, String jwkSetPath, URI authorizationEndpoint,
URI tokenEndpoint, @Nullable URI userinfoEndpoint, @Nullable URI endsessionEndpoint) {
@Nullable URI tokenEndpoint, @Nullable URI userinfoEndpoint,
@Nullable URI endsessionEndpoint) {
this.authorizationEndpoint = Objects.requireNonNull(authorizationEndpoint, "Authorization Endpoint must be provided");
this.tokenEndpoint = Objects.requireNonNull(tokenEndpoint, "Token Endpoint must be provided");
this.tokenEndpoint = tokenEndpoint;
this.userinfoEndpoint = userinfoEndpoint;
this.endsessionEndpoint = endsessionEndpoint;
this.issuer = Objects.requireNonNull(issuer, "OP Issuer must be provided");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -281,25 +281,31 @@ private OpenIdConnectProviderConfiguration buildOpenIdConnectProviderConfigurati
// This should never happen as it's already validated in the settings
throw new SettingsException("Invalid URI: " + OP_AUTHORIZATION_ENDPOINT.getKey(), e);
}
String responseType = require(config, RP_RESPONSE_TYPE);
String tokenEndpointString = config.getSetting(OP_TOKEN_ENDPOINT);
if (responseType.equals("code") && tokenEndpointString.isEmpty()) {
throw new SettingsException("The configuration setting [" + OP_TOKEN_ENDPOINT.getConcreteSettingForNamespace(name()).getKey()
+ "] is required when [" + RP_RESPONSE_TYPE.getConcreteSettingForNamespace(name()).getKey() + "] is set to \"code\"");
}
URI tokenEndpoint;
try {
tokenEndpoint = new URI(require(config, OP_TOKEN_ENDPOINT));
tokenEndpoint = tokenEndpointString.isEmpty() ? null : new URI(tokenEndpointString);
} catch (URISyntaxException e) {
// This should never happen as it's already validated in the settings
throw new SettingsException("Invalid URL: " + OP_TOKEN_ENDPOINT.getKey(), e);
}
URI userinfoEndpoint;
try {
userinfoEndpoint = (config.getSetting(OP_USERINFO_ENDPOINT, () -> null) == null) ? null :
new URI(config.getSetting(OP_USERINFO_ENDPOINT, () -> null));
userinfoEndpoint = (config.getSetting(OP_USERINFO_ENDPOINT).isEmpty()) ? null :
new URI(config.getSetting(OP_USERINFO_ENDPOINT));
} catch (URISyntaxException e) {
// This should never happen as it's already validated in the settings
throw new SettingsException("Invalid URI: " + OP_USERINFO_ENDPOINT.getKey(), e);
}
URI endsessionEndpoint;
try {
endsessionEndpoint = (config.getSetting(OP_ENDSESSION_ENDPOINT, () -> null) == null) ? null :
new URI(config.getSetting(OP_ENDSESSION_ENDPOINT, () -> null));
endsessionEndpoint = (config.getSetting(OP_ENDSESSION_ENDPOINT).isEmpty()) ? null :
new URI(config.getSetting(OP_ENDSESSION_ENDPOINT));
} catch (URISyntaxException e) {
// This should never happen as it's already validated in the settings
throw new SettingsException("Invalid URI: " + OP_ENDSESSION_ENDPOINT.getKey(), e);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public void testInvalidAuthorizationEndpointThrowsError() {
Matchers.containsString(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.OP_AUTHORIZATION_ENDPOINT)));
}

public void testMissingTokenEndpointThrowsError() {
public void testMissingTokenEndpointThrowsErrorInCodeFlow() {
final Settings.Builder settingsBuilder = Settings.builder()
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.OP_AUTHORIZATION_ENDPOINT), "https://op.example.com/login")
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.OP_ISSUER), "https://op.example.com")
Expand All @@ -103,6 +103,22 @@ public void testMissingTokenEndpointThrowsError() {
Matchers.containsString(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.OP_TOKEN_ENDPOINT)));
}

public void testMissingTokenEndpointIsAllowedInImplicitFlow() {
final Settings.Builder settingsBuilder = Settings.builder()
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.OP_AUTHORIZATION_ENDPOINT), "https://op.example.com/login")
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.OP_ISSUER), "https://op.example.com")
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.OP_JWKSET_PATH), "https://op.example.com/jwks.json")
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.PRINCIPAL_CLAIM.getClaim()), "sub")
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.RP_REDIRECT_URI), "https://rp.my.com")
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.RP_CLIENT_ID), "rp-my")
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.RP_RESPONSE_TYPE), "id_token token");
settingsBuilder.setSecureSettings(getSecureSettings());
final OpenIdConnectRealm realm = new OpenIdConnectRealm(buildConfig(settingsBuilder.build()), null, null);
assertNotNull(realm);

}


public void testInvalidTokenEndpointThrowsError() {
final Settings.Builder settingsBuilder = Settings.builder()
.put(getFullSettingKey(REALM_NAME, OpenIdConnectRealmSettings.OP_AUTHORIZATION_ENDPOINT), "https://op.example.com/login")
Expand Down

0 comments on commit 99ddb8b

Please sign in to comment.