-
Notifications
You must be signed in to change notification settings - Fork 7
DiscoveryAndOPConfiguration
Current File(s): conf/idp.properties, jetty-config
Together with the correct servlet container settings, the OIDC plugin offers building blocks for supporting some of the features defined at OpenID Connect Disovery 1.0 specification. This page describes one example configuration with Jetty.
The flows/oidc/webfinger -directory contains a simplified flow for WebFinger. It does not have any input validation features: it responds with a reference to the OIDC issuer for all the valid requests with rel -parameter corresponding to http://openid.net/specs/connect/1.0/issuer
. The resource -paramater in the request is not currently verified or exploited in any way.
The servlet container must be configured to route /.well-known/webfinger -requests to the /idp/profile/oidc/webfinger endpoint.
In Jetty, this can be achieved for instance by enabling the rewrite handler and configuring jetty-rewrite.xml in the following way:
<Configure id="Server" class="org.eclipse.jetty.server.Server">
<Get id="oldhandler" name="handler"/>
<Set name="handler">
<New id="Rewrite" class="org.eclipse.jetty.rewrite.handler.RewriteHandler">
<Set name="handler"><Ref id="oldhandler"/></Set>
<Set name="rewriteRequestURI">true</Set>
<Set name="rewritePathInfo">false</Set>
<Set name="originalPathAttribute">requestedPath</Set>
<Call name="addRule">
<Arg>
<New class="org.eclipse.jetty.rewrite.handler.RewritePatternRule">
<Set name="pattern">/.well-known/webfinger</Set>
<Set name="replacement">/idp/profile/oidc/webfinger</Set>
</New>
</Arg>
</Call>
</New>
</Set>
</Configure>
The request:
https://192.168.0.150/.well-known/webfinger?resource=acct%3Ajoe%40192.168.0.150&rel=http%3A%2F%2Fopenid.net%2Fspecs%2Fconnect%2F1.0%2Fissuer
The response
HTTP/1.1 200 OK
Set-Cookie: JSESSIONID=node0qfvgrby0j9le95rb2319m6mg1.node0;Path=/idp;Secure
Cache-Control: no-store
Content-Type: application/jrd+json;charset=utf-8
Content-Length: 130
Server: Jetty(9.4.2.v20170220)
{"subject":"acct:[email protected]","links":[{"rel":"http://openid.net/specs/connect/1.0/issuer","href":"https://192.168.0.150"}]
The default installation includes a template openid-configuration -file in the static/.well-known directory. That should be configured to exists in the endpoint consisting of the OP issuer and /.well-known/openid-configuration -postfix (e.g. https://192.168.0.150/.well-known/openid-configuration
).
Currently the file must be manually updated to correspond to the configuration in other files (conf/idp.properties, conf/attribute-resolver.xml, etc..). The standard contents of the metadata file is specified here.
There are two ways to publish the OP metadata. Either statically from the file (default), or partially dynamically using the discovery flow.
The servlet container should add Content-Type: application/json
-header when responding with the openid-configuration. In Jetty, this can be achieved for instance by enabling rewrite handler and configuring jetty-rewrite.xml in the following way:
<Configure id="Server" class="org.eclipse.jetty.server.Server">
<Get id="oldhandler" name="handler"/>
<Set name="handler">
<New id="Rewrite" class="org.eclipse.jetty.rewrite.handler.RewriteHandler">
<Set name="handler"><Ref id="oldhandler"/></Set>
<Set name="rewriteRequestURI">true</Set>
<Set name="rewritePathInfo">false</Set>
<Set name="originalPathAttribute">requestedPath</Set>
<Call name="addRule">
<Arg>
<New class="org.eclipse.jetty.rewrite.handler.HeaderPatternRule">
<Set name="pattern">/.well-known/openid-configuration</Set>
<Set name="name">Content-Type</Set>
<Set name="value">application/json</Set>
</New>
</Arg>
</Call>
</New>
</Set>
</Configure>
The servlet container must be configured to route /.well-known/openid-configuration -requests to the /idp/profile/oidc/discovery endpoint.
In Jetty, this can be achieved for instance by enabling the rewrite handler and configuring jetty-rewrite.xml in the following way:
<Configure id="Server" class="org.eclipse.jetty.server.Server">
<Get id="oldhandler" name="handler"/>
<Set name="handler">
<New id="Rewrite" class="org.eclipse.jetty.rewrite.handler.RewriteHandler">
<Set name="handler"><Ref id="oldhandler"/></Set>
<Set name="rewriteRequestURI">true</Set>
<Set name="rewritePathInfo">false</Set>
<Set name="originalPathAttribute">requestedPath</Set>
<Call name="addRule">
<Arg>
<New class="org.eclipse.jetty.rewrite.handler.RewritePatternRule">
<Set name="pattern">/.well-known/openid-configuration</Set>
<Set name="replacement">/idp/profile/oidc/discovery</Set>
</New>
</Arg>
</Call>
</New>
</Set>
</Configure>
After the servlet container has been configured to route the openid-configuration traffic to the discovery flow, the dynamic response claims can be configured in the following way:
In the /opt/shibboleth-idp/flows/oidc/discovery/discovery-beans.xml file:
The bean called shibboleth.oidc.OpenIdConfigurationResolver is the main configuration bean. For it's constructor, a file that will be used as a skeleton for the openid-configuration must be provided. The property called dynamicValueResolvers contains a map of dynamic configuration claims. The map contains 1..n entries, key referring to the name of the claim, and value to the MetadataValueResolver.
See the next subsections for the available MetadataValueResolver implementations.
The global bean set with the idp.oidc.discovery.resolver property is the main configuration bean. By default, its value is shibboleth.oidc.DefaultOpenIdConfigurationResolver, which is defined in the bean declarations inside JAR.
When the property is set to a different value, matching bean definition must implement org.geant.idpextension.oidc.metadata.resolver.ProviderMetadataResolver.
See the next subsections for the available MetadataValueResolver implementations and an example of custom resolver bean (with id=shibboleth.oidc.OpenIdConfigurationResolver).
class: org.geant.idpextension.oidc.metadata.impl.ArrayMetadataValueResolver
Contains an array of other _MetadataValueResolver_s set in a property called embeddedResolvers. The claim name can also be optionally defined in a property called objectName.
class: org.geant.idpextension.oidc.metadata.impl.CredentialMetadataValueResolver
Publishes the public key information from the given Shibboleth IdP credential. It is set with a property called credential.
class: org.geant.idpextension.oidc.metadata.impl.FilesystemMetadataValueResolver
Publishes the contents of the JSON file given in the constructor of the class. Optionally a Timer can also be given in the constructor for timing the refresh of the contents of the file.
The example configuration below uses a file from /opt/shibboleth-idp/static/.well-known/openid-configuration as a skeleton for the OP configuration and adds a claim called signing-keys with a value from a single credential in an array.
<bean id="shibboleth.oidc.OpenIdConfigurationResolver" class="org.geant.idpextension.oidc.metadata.impl.DynamicFilesystemProviderMetadataResolver">
<property name="dynamicValueResolvers">
<map value-type="org.geant.idpextension.oidc.metadata.resolver.MetadataValueResolver">
<entry key="signing-keys" value-ref="ArrayResolverExample" />
</map>
</property>
<constructor-arg type="java.io.File"
value="/opt/shibboleth-idp/static/.well-known/openid-configuration" />
</bean>
<bean id="shibboleth.oidc.DefaultSigningCredential"
class="org.geant.idpextension.oidc.profile.spring.factory.BasicJWKCredentialFactoryBean">
<property name="jWKResource">
<bean class="org.springframework.core.io.FileSystemResource">
<constructor-arg type="java.lang.String"
value="%{idp.signing.oidc.key}" />
</bean>
</property>
</bean>
<bean id="ArrayResolverExample"
class="org.geant.idpextension.oidc.metadata.impl.ArrayMetadataValueResolver"
p:objectName="keys">
<property name="embeddedResolvers">
<list
value-type="org.geant.idpextension.oidc.metadata.resolver.MetadataValueResolver">
<ref bean="CredentialResolver" />
</list>
</property>
</bean>
<bean id="CredentialResolver"
class="org.geant.idpextension.oidc.metadata.impl.CredentialMetadataValueResolver"
p:credential-ref="shibboleth.oidc.DefaultSigningCredential" />
{
"issuer": "https://192.168.0.150",
"authorization_endpoint": "https://192.168.0.150/idp/profile/oidc/authorize",
"registration_endpoint": "https://192.168.0.150/idp/profile/oidc/register",
"token_endpoint": "https://192.168.0.150/idp/profile/oidc/token",
"userinfo_endpoint": "https://192.168.0.150/idp/profile/oidc/userinfo",
"jwks_uri": "https://192.168.0.150/oidc/keyset.jwk",
"response_types_supported": [
"code",
"id_token",
"token id_token",
"code id_token",
"code token",
"code token id_token"
],
"subject_types_supported": [
"public",
"pairwise"
],
"grant_types_supported": [
"authorization_code",
"implicit"
],
"id_token_signing_alg_values_supported": [
"RS256"
],
"token_endpoint_auth_methods_supported": [
"client_secret_basic",
"client_secret_post",
"client_secret_jwt",
"private_key_jwt"
],
"request_parameter_supported": false,
"request_uri_parameter_supported": false,
"require_request_uri_registration": false,
"request_uri_parameter_supported": false,
"scopes_supported": [
"openid",
"profile",
"email",
"address",
"phone",
"info"
],
"claims_supported": [
"aud",
"acr",
"exp",
"iat",
"iss",
"sub",
"eduPersonPrincipalName",
"eduPersonAffiliation",
"mail"
]
}
(Migrated)