Multi-factor Authentication Login
Multi-factor authentication logins can be enforced for users of a certain client in two ways. The first one is configuring the client in the AAI Resource Registry (checkbox "REFEDS Multifactor Authentication Login" in "Intended Audience and Expert Settings") to do so. In this case, the edu-ID OP requires multi-factor authentication, no matter what is specified in the authentication request.
The edu-ID OIDC implementation also supports the use of essential id_token claim request for acr. By adding the following parameter to the OIDC authentication request, a Relying Party can enforce multi-factor authentication for users that want to access the service:
claims=%7B%22id_token%22%3A%7B%22acr%22%3A%20%7B%22essential%22%3A%20true%2C%22values%22%3A%20%5B%22https%3A%2F%2Frefeds.org%2Fprofile%2Fmfa%22%5D%7D%7D%7D
URL-encoded version of:
claims = { "id_token": { "acr":
{ "essential": true, "values": ["https://refeds.org/profile/mfa"] } } }
Reference 5.5.1.1 Requesting the 'acr' claim
Like this, a client is able to enforce multi-factor authentication only in some situations or for some users while not enforcing it for others.
We provide examples extending the configurations from above:
Just enable the OIDCProviderAuthorizationEndpoint in the configuration file:
OIDCProviderAuthorizationEndpoint https://login.test.eduid.ch/idp/profile/oidc/authorize?claims=%7B%22id_token%22%3A%7B%22acr%22%3A%20%7B%22essential%22%3A%20true%2C%22values%22%3A%20%5B%22https%3A%2F%2Frefeds.org%2Fprofile%2Fmfa%22%5D%7D%7D%7D
To enforce two-step login, add the above acr claim to the original authentication request. This also works for users already authenticated in the service for whom the second factor is subsequently requested.
Usage of the acr_values request parameter
The OIDC core specifications also define the authorize request parameter 'acr_values'. It is a shorthand for the request of ID Token acr claim as mentioned above, however without specifying essential=true. That means, it only asks for MFA without enforcing it. This is the default behavior of the edu-ID OP: Enforcing MFA if the user has it configured or either the organisation policy or the client enforces it, else not asking for it. Setting 'acr_values' only hence has no effect.
However, it is important to note that according to the specifications, when using both the acr_values parameter and the ID Token ACR claim request as above, "the resulting behavior is unspecified". Clients should therefore never use both in the same request.
Verifying that MFA has been used
A client can verify in the ID Token if the user is authenticated with MFA at the OP. This can be done regardless of whether MFA has been enforced via the authorize request.
The user has an MFA session at the OP if and only if the ID Token contains the 'acr' claim with value 'https://refeds.org./profile/mfa'. Clients which enforce MFA are encouraged to check this after receiving the ID Token and before establishing the client-side user session.
Specify the authorization URI in addition to the issuer URI.
spring:
security:
oauth2:
client:
registration:
eduid:
client-id: my_unique_client_id
scope: openid,profile,email
authorization-grant-type: authorization_code
redirect-uri: https://example.com/protected/redirect_uri
client-authentication-method: private_key_jwt
client-name: my_client_name
provider:
eduid:
issuer-uri: https://login.test.eduid.ch/
authorization-uri: https://login.test.eduid.ch/idp/profile/oidc/authorize?claims=%7B%22id_token%22%3A%7B%22acr%22%3A%20%7B%22essential%22%3A%20true%2C%22values%22%3A%20%5B%22https%3A%2F%2Frefeds.org%2Fprofile%2Fmfa%22%5D%7D%7D%7D
ngOnInit(): void {
this.oauthService.configure(authCodeFlowConfig);
this.oauthService.loadDiscoveryDocument();
// Need to adjust the login URL after loading the Discovery Document (.well-known/openid-configuration)
this.oauthService.loginUrl = 'https://login.test.eduid.ch/idp/profile/oidc/authorize?claims=%7B%22id_token%22%3A%7B%22acr%22%3A%20%7B%22essential%22%3A%20true%2C%22values%22%3A%20%5B%22https%3A%2F%2Frefeds.org%2Fprofile%2Fmfa%22%5D%7D%7D%7D',
this.oauthService.initLoginFlow();
// Automatically load user profile
this.oauthService.events
.pipe(filter((e) => e.type === 'token_received'))
.subscribe((_) => this.oauthService.loadUserProfile());
}