Add ability to configure custom email and username claims

This will help customers support active directory-based OIDC
This commit is contained in:
Joseph Schorr 2018-09-07 15:26:32 -04:00
parent 5240140a96
commit 90c0e34945
3 changed files with 51 additions and 3 deletions

View file

@ -1201,6 +1201,32 @@
</div>
</td>
</tr>
<tr>
<td>Verified E-mail Address Claim (optional):</td>
<td>
<span class="config-string-field"
binding="config[provider].VERIFIED_EMAIL_CLAIM_NAME"
placeholder="User information JWT claim that contains the verified e-mail"
is-optional="true">
</span>
<div class="help-text">
If specified, the claim in the User Information JWT that contains the verified e-mail address for the user.
</div>
</td>
</tr>
<tr>
<td>Preferred Username Claim (optional):</td>
<td>
<span class="config-string-field"
binding="config[provider].PREFERRED_USERNAME_CLAIM_NAME"
placeholder="User information JWT claim that contains the preferred username"
is-optional="true">
</span>
<div class="help-text">
If specified, the claim in the User Information JWT that contains the preferred username for the user.
</div>
</td>
</tr>
<tr ng-if="config.AUTHENTICATION_TYPE != 'Database' && config.AUTHENTICATION_TYPE != 'AppToken'">
<td>Binding Field:</td>
<td>

View file

@ -167,13 +167,32 @@ class OIDCLoginService(OAuthService):
raise OAuthLoginException('Mismatch in `sub` returned by OIDC user info endpoint')
# Check if we have a verified email address.
if self.config.get('VERIFIED_EMAIL_CLAIM_NAME'):
email_address = user_info.get(self.config['VERIFIED_EMAIL_CLAIM_NAME'])
else:
email_address = user_info.get('email') if user_info.get('email_verified') else None
logger.debug('Found e-mail address `%s` for sub `%s`', email_address, user_info['sub'])
if self._mailing:
if email_address is None:
raise OAuthLoginException('A verified email address is required to login with this service')
# Check for a preferred username.
lusername = user_info.get('preferred_username') or user_info.get('sub')
if self.config.get('PREFERRED_USERNAME_CLAIM_NAME'):
lusername = user_info.get(self.config['PREFERRED_USERNAME_CLAIM_NAME'])
else:
lusername = user_info.get('preferred_username')
if lusername is None:
# Note: Active Directory provides `unique_name` and `upn`.
# https://docs.microsoft.com/en-us/azure/active-directory/develop/v1-id-and-access-tokens
lusername = user_info.get('unique_name', user_info.get('upn'))
if lusername is None:
lusername = user_info['sub']
if lusername.find('@') >= 0:
lusername = lusername[0:lusername.find('@')]
return decoded_id_token['sub'], lusername, email_address
@property

View file

@ -51,7 +51,7 @@ def email_verified(request):
def userinfo_supported(request):
return request.param
@pytest.fixture(params=["someusername", None])
@pytest.fixture(params=["someusername", "foo@bar.com", None])
def preferred_username(request):
return request.param
@ -334,6 +334,9 @@ def test_exchange_code_validcode(oidc_service, discovery_handler, app_config, ht
assert lemail is None
if preferred_username is not None:
if preferred_username.find('@') >= 0:
preferred_username = preferred_username[0:preferred_username.find('@')]
assert lusername == preferred_username
else:
assert lusername == lid