Skip to content

Commit

Permalink
Add support for extra_claims (#443)
Browse files Browse the repository at this point in the history
* Add support for extra_claims
  • Loading branch information
tpazderka authored Dec 1, 2017
1 parent 81e5791 commit c0f8292
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 3 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ The format is based on the [KeepAChangeLog] project.

## 0.13.0 [Unreleased]

### Added
- [#443] Ability to specify additional supported claims for oic.Provider

### Fixed
- [#430] Audience of a client assertion is endpoint dependent.
- [#427] Made matching for response_types order independent for authorization requests
Expand All @@ -17,6 +20,7 @@ The format is based on the [KeepAChangeLog] project.
[#427]: https://github.com/OpenIDC/pyoidc/pull/427
[#399]: https://github.com/OpenIDC/pyoidc/issues/399
[#436]: https://github.com/OpenIDC/pyoidc/pull/436
[#443]: https://github.com/OpenIDC/pyoidc/pull/443

## 0.12.0 [2017-09-25]

Expand Down
7 changes: 6 additions & 1 deletion src/oic/oic/provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,8 @@ def __init__(self, name, sdb, cdb, authn_broker, userinfo, authz,
client_authn, symkey=None, urlmap=None, ca_certs="", keyjar=None,
hostname="", template_lookup=None, template=None,
verify_ssl=True, capabilities=None, schema=OpenIDSchema,
jwks_uri='', jwks_name='', baseurl=None, client_cert=None):
jwks_uri='', jwks_name='', baseurl=None, client_cert=None,
extra_claims=None):

AProvider.__init__(self, name, sdb, cdb, authn_broker, authz,
client_authn, symkey, urlmap, ca_bundle=ca_certs,
Expand Down Expand Up @@ -270,6 +271,8 @@ def __init__(self, name, sdb, cdb, authn_broker, userinfo, authz,
self.preferred_id_type = "public"
self.hostname = hostname or socket.gethostname()

self.extra_claims = extra_claims

for endp in self.endp:
if endp.etype == 'registration':
endpoint = urljoin(self.baseurl, endp.url)
Expand Down Expand Up @@ -1692,6 +1695,8 @@ def provider_features(self, pcr_class=ProviderConfigurationResponse):
_claims = []
for _cl in SCOPE2CLAIMS.values():
_claims.extend(_cl)
if self.extra_claims is not None:
_claims.extend(self.extra_claims)
_provider_info["claims_supported"] = list(set(_claims))

_scopes = list(SCOPE2CLAIMS.keys())
Expand Down
59 changes: 57 additions & 2 deletions tests/test_oic_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,8 @@
"nickname": "Linda",
"email": "linda@example.com",
"verified": True,
"sub": "username"
"sub": "username",
"extra_claim": "extra_claim_value",
}
}

Expand Down Expand Up @@ -183,7 +184,7 @@ def create_provider(self, session_db_factory):
keyjar=KEYJAR)
self.provider.baseurl = self.provider.name

self.cons = Consumer({}, CONSUMER_CONFIG, CLIENT_CONFIG,
self.cons = Consumer({}, CONSUMER_CONFIG.copy(), CLIENT_CONFIG,
server_info=SERVER_INFO, )
self.cons.behaviour = {
"request_object_signing_alg": DEF_SIGN_ALG["openid_request_object"]}
Expand Down Expand Up @@ -215,6 +216,12 @@ def test_authorization_endpoint(self):
assert parsed["state"][0] == "id-6da9ca0cc23959f5f33e8becd9b08cae"
assert "code" in parsed

def test_provider_features_extra_claims(self):
self.provider.extra_claims = ['claim_1', 'claim_2']
features = self.provider.provider_features()
assert 'claim_1' in features['claims_supported']
assert 'claim_2' in features['claims_supported']

def test_authorization_endpoint_request(self):
bib = {"scope": ["openid"],
"state": "id-6da9ca0cc23959f5f33e8becd9b08cae",
Expand Down Expand Up @@ -663,6 +670,54 @@ def test_userinfo_endpoint(self):
ident = OpenIDSchema().deserialize(resp.message, "json")
assert _eq(ident.keys(), ['nickname', 'sub', 'name', 'email'])

def test_userinfo_endpoint_extra_claim(self):
# We have to recreate the cache again
self.provider.extra_claims = ['extra_claim']
self.provider.capabilities = self.provider.provider_features()

self.cons.client_secret = "drickyoughurt"
self.cons.config["response_type"] = ["token"]
self.cons.config["request_method"] = "parameter"
# Request the extra claim
self.cons.consumer_config['user_info'] = {'extra_claim': None}
state, location = self.cons.begin("openid", "token",
path="http://localhost:8087")

resp = self.provider.authorization_endpoint(
request=urlparse(location).query)

# redirect
atr = AuthorizationResponse().deserialize(
urlparse(resp.message).fragment, "urlencoded")

uir = UserInfoRequest(access_token=atr["access_token"], schema="openid")

resp = self.provider.userinfo_endpoint(request=uir.to_urlencoded())
ident = OpenIDSchema().deserialize(resp.message, "json")
assert _eq(ident.keys(), ['sub', 'extra_claim'])

def test_userinfo_endpoint_unknown_claim(self):
self.cons.client_secret = "drickyoughurt"
self.cons.config["response_type"] = ["token"]
self.cons.config["request_method"] = "parameter"
# Request the extra claim
self.cons.consumer_config['user_info'] = {'extra_claim': None}
state, location = self.cons.begin("openid", "token",
path="http://localhost:8087")

resp = self.provider.authorization_endpoint(
request=urlparse(location).query)

# redirect
atr = AuthorizationResponse().deserialize(
urlparse(resp.message).fragment, "urlencoded")

uir = UserInfoRequest(access_token=atr["access_token"], schema="openid")

resp = self.provider.userinfo_endpoint(request=uir.to_urlencoded())
ident = OpenIDSchema().deserialize(resp.message, "json")
assert _eq(ident.keys(), ['sub'])

def test_userinfo_endpoint_authn(self):
self.cons.client_secret = "drickyoughurt"
self.cons.config["response_type"] = ["token"]
Expand Down

0 comments on commit c0f8292

Please sign in to comment.