Fixed method name screw-up.

This commit is contained in:
Roland Hedberg 2014-01-22 14:49:46 +01:00
parent dc67e73afd
commit 63e20151f9
26 changed files with 1179 additions and 128 deletions

View File

@ -1,4 +1,4 @@
from oic.oauth2.exception import FailedAuthentication
from oic.exception import FailedAuthentication
from oic.oic import OpenIDSchema
from oic.utils.http_util import Response

View File

@ -132,7 +132,8 @@ class OpenIDConnect(Social):
session.setService(self.opKey)
acr_value = session.getAcrValue(client.authorization_endpoint)
try:
acr_values = client.provider_info[self.srv_discovery_url]["acr_values"].split()
acr_values = client.provider_info[
self.srv_discovery_url]["acr_values_supported"].split()
session.setAcrvalues(acr_values)
except:
pass

View File

@ -139,7 +139,8 @@ class OpenIDConnect(object):
session.setClient(client)
acr_value = session.getAcrValue(client.authorization_endpoint)
try:
acr_values = client.provider_info[self.srv_discovery_url]["acr_values"].split()
acr_values = client.provider_info[
self.srv_discovery_url]["acr_values_supported"].split()
session.setAcrvalues(acr_values)
except:
pass

View File

@ -64,3 +64,7 @@ class NotForMe(PyoidcError):
class UnSupported(Exception):
pass
class MessageException(PyoidcError):
pass

View File

@ -13,7 +13,7 @@ import logging
from oic.utils.keyio import KeyJar
from oic.utils.time_util import utc_time_sans_frac
from oic.oauth2.exception import UnSupported
from oic.exception import UnSupported
DEF_SIGN_ALG = "HS256"

639
src/oic/oauth2/dynreg.py Normal file
View File

@ -0,0 +1,639 @@
import logging
import urllib
import urlparse
from oic.oic import OIDCONF_PATTERN
from oic.oic.message import ProviderConfigurationResponse
import requests
from oic.utils.keyio import KeyJar
from oic.utils.time_util import utc_time_sans_frac
from oic.oic.provider import secret
from oic.oic.provider import RegistrationEndpoint
from oic.oic.provider import Endpoint
from oic import oauth2
from oic.oauth2 import provider
from oic.oauth2 import VerificationError
from oic.oauth2 import rndstr
from oic.oauth2 import ErrorResponse
from oic.oauth2 import UnSupported
from oic.oauth2 import Message
from oic.oauth2 import message
from oic.oauth2 import SINGLE_REQUIRED_STRING
from oic.oauth2 import OPTIONAL_LIST_OF_SP_SEP_STRINGS
from oic.oauth2 import REQUIRED_LIST_OF_STRINGS
from oic.oauth2 import OPTIONAL_LIST_OF_STRINGS
from oic.oauth2 import SINGLE_OPTIONAL_STRING
from oic.oauth2 import SINGLE_OPTIONAL_INT
from oic.exception import UnknownAssertionType, PyoidcError
from oic.utils.authn.client import AuthnFailure
from oic.utils.http_util import Unauthorized, NoContent
from oic.utils.http_util import Response
from oic.utils.http_util import BadRequest
from oic.utils.http_util import Forbidden
logger = logging.getLogger(__name__)
__author__ = 'roland'
# -----------------------------------------------------------------------------
class InvalidRedirectUri(Exception):
pass
class MissingPage(Exception):
pass
class ModificationForbidden(Exception):
pass
class RegistrationRequest(Message):
c_param = {
"redirect_uris": REQUIRED_LIST_OF_STRINGS,
"client_name": SINGLE_OPTIONAL_STRING,
"client_uri": SINGLE_OPTIONAL_STRING,
"logo_uri": SINGLE_OPTIONAL_STRING,
"contacts": OPTIONAL_LIST_OF_STRINGS,
"tos_uri": SINGLE_OPTIONAL_STRING,
"policy_uri": SINGLE_OPTIONAL_STRING,
"token_endpoint_auth_method": SINGLE_OPTIONAL_STRING,
"scope": OPTIONAL_LIST_OF_SP_SEP_STRINGS,
"grant_types": OPTIONAL_LIST_OF_STRINGS,
"response_types": OPTIONAL_LIST_OF_STRINGS,
"jwks_uri": SINGLE_OPTIONAL_STRING,
"software_id": SINGLE_OPTIONAL_STRING,
"software_version": SINGLE_OPTIONAL_STRING,
}
def verify(self, **kwargs):
if "initiate_login_uri" in self:
assert self["initiate_login_uri"].startswith("https:")
if "redirect_uris" in self:
for uri in self["redirect_uris"]:
if urlparse.urlparse(uri).fragment:
raise InvalidRedirectUri(
"redirect_uri contains fragment: %s" % uri)
for uri in ["client_uri", "logo_uri", "tos_uri", "policy_uri"]:
if uri in self:
try:
resp = requests.request("GET", self[uri],
allow_redirects=True)
except requests.ConnectionError:
raise MissingPage(self[uri])
if not resp.status_code in [200, 201]:
raise MissingPage(self[uri])
if "grant_types" in self and "response_types" in self:
for typ in self["grant_types"]:
if typ == "authorization_code":
try:
assert "code" in self["response_types"]
except AssertionError:
self["response_types"].append("code")
elif typ == "implicit":
try:
assert "token" in self["response_types"]
except AssertionError:
self["response_types"].append("token")
return super(RegistrationRequest, self).verify(**kwargs)
class ClientInfoResponse(RegistrationRequest):
c_param = RegistrationRequest.c_param.copy()
c_param.update({
"client_id": SINGLE_REQUIRED_STRING,
"client_secret": SINGLE_OPTIONAL_STRING,
"client_id_issued_at": SINGLE_OPTIONAL_INT,
"client_secret_expires_at": SINGLE_OPTIONAL_INT,
"registration_access_token": SINGLE_REQUIRED_STRING,
"registration_client_uri": SINGLE_REQUIRED_STRING
})
class ClientRegistrationError(ErrorResponse):
c_param = ErrorResponse.c_param.copy()
c_param.update({"state": SINGLE_OPTIONAL_STRING})
c_allowed_values = ErrorResponse.c_allowed_values.copy()
c_allowed_values.update({"error": ["invalid_redirect_uri",
"invalid_client_metadata",
"invalid_client_id"]})
class ClientUpdateRequest(RegistrationRequest):
c_param = RegistrationRequest.c_param.copy()
c_param.update({
"client_id": SINGLE_REQUIRED_STRING,
"client_secret": SINGLE_OPTIONAL_STRING,
})
MSG = {
"RegistrationRequest": RegistrationRequest,
"ClientInfoResponse": ClientInfoResponse,
"ClientRegistrationError": ClientRegistrationError,
"ClientUpdateRequest": ClientUpdateRequest
}
def factory(msgtype):
try:
return MSG[msgtype]
except KeyError:
return message.factory(msgtype)
# -----------------------------------------------------------------------------
class ClientInfoEndpoint(Endpoint):
etype = "clientinfo"
class Provider(provider.Provider):
def __init__(self, name, sdb, cdb, authn_broker, authz, client_authn,
symkey="", urlmap=None, iv=0, default_scope="",
ca_bundle=None, seed="", client_authn_methods=None,
authn_at_registration="", client_info_url="",
secret_lifetime=86400):
provider.Provider.__init__(self, name, sdb, cdb, authn_broker, authz,
client_authn, symkey, urlmap, iv,
default_scope, ca_bundle)
self.endp.extend([RegistrationEndpoint, ClientInfoEndpoint])
# dictionary of client authentication methods
self.client_authn_methods = client_authn_methods
if authn_at_registration:
assert authn_at_registration in client_authn_methods
self.authn_at_registration = authn_at_registration
self.seed = seed
self.client_info_url = client_info_url
self.secret_lifetime = secret_lifetime
# @staticmethod
# def _uris_to_dict(uris):
# ruri = {}
# for uri in uris:
# base, query = urllib.splitquery(uri)
# if query:
# try:
# ruri[base].append(urlparse.parse_qs(query))
# except KeyError:
# ruri[base] = [urlparse.parse_qs(query)]
# else:
# ruri[base] = [""]
# return ruri
#
# @staticmethod
# def _dict_to_uris(spec):
# _uri = []
# for url, qlist in spec.items():
# for query in qlist:
# if query:
# _uri.append("%s?%s" % (url, query))
# else:
# _uri.append(url)
# return _uri
@staticmethod
def _uris_to_tuples(uris):
tup = []
for uri in uris:
base, query = urllib.splitquery(uri)
if query:
tup.append((base, query))
else:
tup.append((base,""))
return tup
@staticmethod
def _tuples_to_uris(items):
_uri = []
for url, query in items:
if query:
_uri.append("%s?%s" % (url, query))
else:
_uri.append(url)
return _uri
def create_new_client(self, request):
"""
:param request: The Client registration request
:return: The client_id
"""
_cinfo = request.to_dict()
# create new id and secret
_id = rndstr(12)
while _id in self.cdb:
_id = rndstr(12)
_cinfo["client_id"] = _id
_cinfo["client_secret"] = secret(self.seed, _id)
_cinfo["client_id_issued_at"] = utc_time_sans_frac()
_cinfo["client_secret_expires_at"] = utc_time_sans_frac() + \
self.secret_lifetime
# If I support client info endpoint
if ClientInfoEndpoint in self.endp:
_cinfo["registration_access_token"] = rndstr(32)
_cinfo["registration_client_uri"] = "%s%s?client_id=%s" % (
self.client_info_url, ClientInfoEndpoint.etype, _id)
if "redirect_uris" in request:
_cinfo["redirect_uris"] = self._uris_to_tuples(
request["redirect_uris"])
self.cdb[_id] = _cinfo
return _id
def client_info(self, client_id):
_cinfo = self.cdb[client_id].copy()
try:
_cinfo["redirect_uris"] = self._tuples_to_uris(
_cinfo["redirect_uris"])
except KeyError:
pass
msg = ClientInfoResponse(**_cinfo)
return Response(msg.to_json(), content="application/json")
def client_info_update(self, client_id, request):
_cinfo = self.cdb[client_id].copy()
try:
_cinfo["redirect_uris"] = self._tuples_to_uris(
_cinfo["redirect_uris"])
except KeyError:
pass
for key, value in request.items():
if key in ["client_secret", "client_id"]:
# assure it's the same
try:
assert value == _cinfo[key]
except AssertionError:
raise ModificationForbidden("Not allowed to change")
else:
_cinfo[key] = value
for key in _cinfo.keys():
if key in ["client_id_issued_at", "client_secret_expires_at",
"registration_access_token","registration_client_uri"]:
continue
if key not in request:
del _cinfo[key]
if "redirect_uris" in request:
_cinfo["redirect_uris"] = self._uris_to_tuples(
request["redirect_uris"])
self.cdb[client_id] = _cinfo
def verify_client(self, environ, areq, authn_method, client_id=""):
"""
:param areq: The request
:param authn_method: client authentication method
:return:
"""
if not client_id:
client_id = self.get_client_id(areq, environ["HTTP_AUTHORIZATION"])
try:
method = self.client_authn_methods[authn_method]
except KeyError:
raise UnSupported()
return method(self).verify(environ, client_id=client_id)
def registration_endpoint(self, request, environ, **kwargs):
"""
:param request: The request
:param authn: Client authentication information
:param kwargs: extra keyword arguments
:return: A Response instance
"""
_request = RegistrationRequest().deserialize(request, "json")
try:
_request.verify()
except InvalidRedirectUri, err:
msg = ClientRegistrationError(error="invalid_redirect_uri",
error_description="%s" % err)
return BadRequest(msg.to_json(), content="application/json")
except (MissingPage, VerificationError), err:
msg = ClientRegistrationError(error="invalid_client_metadata",
error_description="%s" % err)
return BadRequest(msg.to_json(), content="application/json")
# authenticated client
if self.authn_at_registration:
try:
_ = self.verify_client(environ, _request,
self.authn_at_registration)
except (AuthnFailure, UnknownAssertionType):
return Unauthorized()
client_id = self.create_new_client(_request)
return self.client_info(client_id)
def client_info_endpoint(self, request, environ,
method="GET", query="", **kwargs):
"""
Operations on this endpoint are switched through the use of different
HTTP methods
:param request: The request
:param authn: Client authentication information
:param method: HTTP method used for the request
:param query: The query part of the URL used, this is where the
client_id is supposed to reside.
:param kwargs: extra keyword arguments
:return: A Response instance
"""
_query = urlparse.parse_qs(query)
try:
_id = _query["client_id"][0]
except KeyError:
return BadRequest("Missing query component")
try:
assert _id in self.cdb
except AssertionError:
return Unauthorized()
# authenticated client
try:
_ = self.verify_client(environ, request, "bearer_header",
client_id=_id)
except (AuthnFailure, UnknownAssertionType):
return Unauthorized()
if method == "GET":
return self.client_info(_id)
elif method == "PUT":
try:
_request = ClientUpdateRequest().from_json(request)
except ValueError:
return BadRequest()
try:
_request.verify()
except InvalidRedirectUri, err:
msg = ClientRegistrationError(error="invalid_redirect_uri",
error_description="%s" % err)
return BadRequest(msg.to_json(), content="application/json")
except (MissingPage, VerificationError), err:
msg = ClientRegistrationError(error="invalid_client_metadata",
error_description="%s" % err)
return BadRequest(msg.to_json(), content="application/json")
try:
self.client_info_update(_id, _request)
return self.client_info(_id)
except ModificationForbidden:
return Forbidden()
elif method == "DELETE":
try:
del self.cdb[_id]
except KeyError:
return Unauthorized()
else:
return NoContent()
def providerinfo_endpoint(self):
pass
RESPONSE2ERROR = {
"ClientInfoResponse": [ClientRegistrationError],
"ClientUpdateRequest": [ClientRegistrationError]
}
class Client(oauth2.Client):
def __init__(self, client_id=None, ca_certs=None,
client_authn_method=None, keyjar=None):
oauth2.Client.__init__(self, client_id=client_id, ca_certs=ca_certs,
client_authn_method=client_authn_method,
keyjar=keyjar)
self.allow = {}
self.request2endpoint.update({
"RegistrationRequest": "registration_endpoint",
"ClientUpdateRequest": "clientinfo_endpoint"
})
self.registration_response = None
def construct_RegistrationRequest(self, request=RegistrationRequest,
request_args=None, extra_args=None,
**kwargs):
if request_args is None:
request_args = {}
return self.construct_request(request, request_args, extra_args)
def do_client_registration(self, request=RegistrationRequest,
body_type="", method="GET",
request_args=None, extra_args=None,
http_args=None,
response_cls=ClientInfoResponse,
**kwargs):
url, body, ht_args, csi = self.request_info(request, method,
request_args, extra_args,
**kwargs)
if http_args is None:
http_args = ht_args
else:
http_args.update(http_args)
resp = self.request_and_return(url, response_cls, method, body,
body_type, http_args=http_args)
return resp
def do_client_read_request(self, request=ClientUpdateRequest,
body_type="", method="GET",
request_args=None, extra_args=None,
http_args=None,
response_cls=ClientInfoResponse,
**kwargs):
url, body, ht_args, csi = self.request_info(request, method,
request_args, extra_args,
**kwargs)
if http_args is None:
http_args = ht_args
else:
http_args.update(http_args)
resp = self.request_and_return(url, response_cls, method, body,
body_type, http_args=http_args)
return resp
def do_client_update_request(self, request=ClientUpdateRequest,
body_type="", method="PUT",
request_args=None, extra_args=None,
http_args=None,
response_cls=ClientInfoResponse,
**kwargs):
url, body, ht_args, csi = self.request_info(request, method,
request_args, extra_args,
**kwargs)
if http_args is None:
http_args = ht_args
else:
http_args.update(http_args)
resp = self.request_and_return(url, response_cls, method, body,
body_type, http_args=http_args)
return resp
def do_client_delete_request(self, request=ClientUpdateRequest,
body_type="", method="DELETE",
request_args=None, extra_args=None,
http_args=None,
response_cls=ClientInfoResponse,
**kwargs):
url, body, ht_args, csi = self.request_info(request, method,
request_args, extra_args,
**kwargs)
if http_args is None:
http_args = ht_args
else:
http_args.update(http_args)
resp = self.request_and_return(url, response_cls, method, body,
body_type, http_args=http_args)
return resp
def handle_provider_config(self, pcr, issuer, keys=True, endpoints=True):
"""
Deal with Provider Config Response
:param pcr: The ProviderConfigResponse instance
:param issuer: The one I thought should be the issuer of the config
:param keys: Should I deal with keys
:param endpoints: Should I deal with endpoints, that is store them
as attributes in self.
"""
if "issuer" in pcr:
_pcr_issuer = pcr["issuer"]
if pcr["issuer"].endswith("/"):
if issuer.endswith("/"):
_issuer = issuer
else:
_issuer = issuer + "/"
else:
if issuer.endswith("/"):
_issuer = issuer[:-1]
else:
_issuer = issuer
try:
_ = self.allow["issuer_mismatch"]
except KeyError:
try:
assert _issuer == _pcr_issuer
except AssertionError:
raise PyoidcError(
"provider info issuer mismatch '%s' != '%s'" % (
_issuer, _pcr_issuer))
self.provider_info[_pcr_issuer] = pcr
else:
_pcr_issuer = issuer
if endpoints:
for key, val in pcr.items():
if key.endswith("_endpoint"):
setattr(self, key, val)
if keys:
if self.keyjar is None:
self.keyjar = KeyJar()
self.keyjar.load_keys(pcr, _pcr_issuer)
def provider_config(self, issuer, keys=True, endpoints=True,
response_cls=ProviderConfigurationResponse,
serv_pattern=OIDCONF_PATTERN):
if issuer.endswith("/"):
_issuer = issuer[:-1]
else:
_issuer = issuer
url = serv_pattern % _issuer
pcr = None
r = self.http_request(url)
if r.status_code == 200:
pcr = response_cls().from_json(r.text)
elif r.status_code == 302:
while r.status_code == 302:
r = self.http_request(r.headers["location"])
if r.status_code == 200:
pcr = response_cls().from_json(r.text)
break
if pcr is None:
raise PyoidcError("Trying '%s', status %s" % (url, r.status_code))
self.handle_provider_config(pcr, issuer, keys, endpoints)
return pcr
def store_registration_info(self, reginfo):
self.registration_response = reginfo
self.client_secret = reginfo["client_secret"]
self.client_id = reginfo["client_id"]
self.redirect_uris = reginfo["redirect_uris"]
def handle_registration_info(self, response):
if response.status_code == 200:
resp = ClientInfoResponse().deserialize(response.text, "json")
self.store_registration_info(resp)
else:
err = ErrorResponse().deserialize(response.text, "json")
raise PyoidcError("Registration failed: %s" % err.get_json())
return resp
def register(self, url, **kwargs):
"""
Register the client at an OP
:param url: The OPs registration endpoint
:param kwargs: parameters to the registration request
:return:
"""
req = self.construct_RegistrationRequest(**kwargs)
headers = {"content-type": "application/json"}
rsp = self.http_request(url, "POST", data=req.to_json(),
headers=headers)
return self.handle_registration_info(rsp)

View File

@ -8,15 +8,12 @@ import jwkest
from jwkest.jwe import JWE
from jwkest.jwk import keyitems2keyreps
from jwkest.jws import JWS
from oic.oauth2.exception import PyoidcError
from oic.exception import PyoidcError
from oic.exception import MessageException
logger = logging.getLogger(__name__)
class MessageException(PyoidcError):
pass
class MissingRequiredAttribute(MessageException):
def __init__(self, attr):
Exception.__init__(self)
@ -652,7 +649,8 @@ class Message(object):
def from_jwe(self, msg, keys):
krs = keyitems2keyreps(keys)
jwe = JWE()
return self.from_json(jwe.decrypt(msg, krs))
_res = jwe.decrypt(msg, krs)
return self.from_json(_res[0])
# =============================================================================

View File

@ -3,6 +3,7 @@ import traceback
import sys
import urllib
import urlparse
from oic.utils.sdb import AccessCodeUsed
__author__ = 'rohe0002'
@ -10,11 +11,12 @@ import base64
import logging
import os
from oic.oauth2.exception import MissingParameter, URIError
from oic.oauth2.exception import RedirectURIError
from oic.oauth2.exception import ParameterError
from oic.oauth2.exception import FailedAuthentication
from oic.oauth2.exception import UnknownClient
from oic.exception import MissingParameter
from oic.exception import URIError
from oic.exception import RedirectURIError
from oic.exception import ParameterError
from oic.exception import FailedAuthentication
from oic.exception import UnknownClient
from oic.oauth2.message import AccessTokenResponse
from oic.oauth2.message import ErrorResponse
@ -28,7 +30,8 @@ from oic.oauth2.message import MissingRequiredAttribute
from oic.oauth2.message import TokenErrorResponse
from oic.oauth2.message import AccessTokenRequest
from oic.utils.http_util import BadRequest, CookieDealer
from oic.utils.http_util import BadRequest
from oic.utils.http_util import CookieDealer
from oic.utils.http_util import make_cookie
from oic.utils.http_util import Redirect
from oic.utils.http_util import Response
@ -82,7 +85,7 @@ def token_response(**kwargs):
_areq = kwargs["areq"]
_scode = kwargs["scode"]
_sdb = kwargs["sdb"]
_dic = _sdb.update_to_token(_scode, issue_refresh=False)
_dic = _sdb.upgrade_to_token(_scode, issue_refresh=False)
aresp = AccessTokenResponse(**by_schema(AccessTokenResponse, **_dic))
if "state" in _areq:
@ -217,10 +220,10 @@ class Provider(object):
def authn_reply(self, areq, aresp, bsid, **kwargs):
"""
:param areq:
:param aresp:
:param bsid:
:param kwargs:
:param areq: Authorization Request
:param aresp: Authorization Response
:param bsid: Session id
:param kwargs: Additional keyword args
:return:
"""
if "redirect_uri" in areq:
@ -253,7 +256,8 @@ class Provider(object):
return self.response_type_map[_rtype](areq=areq, scode=scode,
sdb=self.sdb)
def input(self, query="", post=None):
@staticmethod
def input(query="", post=None):
# Support GET and POST
if query:
return query
@ -262,18 +266,21 @@ class Provider(object):
else:
raise MissingParameter("No input")
def _error_response(self, error, descr=None):
@staticmethod
def _error_response(error, descr=None):
logger.error("%s" % error)
response = ErrorResponse(error=error, error_description=descr)
return Response(response.to_json(), content="application/json",
status="400 Bad Request")
def _error(self, error, descr=None):
@staticmethod
def _error(error, descr=None):
response = ErrorResponse(error=error, error_description=descr)
return Response(response.to_json(), content="application/json",
status="400 Bad Request")
def _authz_error(self, error, descr=None):
@staticmethod
def _authz_error(error, descr=None):
response = AuthorizationErrorResponse(error=error)
if descr:
@ -282,7 +289,8 @@ class Provider(object):
return Response(response.to_json(), content="application/json",
status="400 Bad Request")
def _redirect_authz_error(self, error, redirect_uri, descr=None):
@staticmethod
def _redirect_authz_error(error, redirect_uri, descr=None):
err = ErrorResponse(error=error)
if descr:
err["error_description"] = descr
@ -451,26 +459,26 @@ class Provider(object):
except KeyError:
oidc_req = None
sinfo = self.sdb.create_authz_session(user, areq, oidreq=oidc_req)
skey = self.sdb.create_authz_session(user, areq, oidreq=oidc_req)
# Now about the authorization step.
try:
permissions = self.authz.permissions(cookie)
if not permissions:
return self.authz(user, sinfo)
return self.authz(user, skey)
except (ToOld, TamperAllert):
return self.authz(user, areq, sinfo)
return self.authz(user, areq, skey)
return self.authz_part2(user, areq, sinfo, permissions, _authn)
return self.authz_part2(user, areq, skey, permissions, _authn)
def authz_part2(self, user, areq, sinfo, permission=None, authn=None,
def authz_part2(self, user, areq, skey, permission=None, authn=None,
**kwargs):
"""
After the authentication this is where you should end up
:param user:
:param areq: The Authorization Request
:param sinfo: Session information
:param skey: Session key
:param permission: A permission specification
:param authn: The Authentication Method used
:param kwargs: possible other parameters
@ -479,7 +487,7 @@ class Provider(object):
_log_debug = logger.debug
_log_debug("- in authenticated() -")
sinfo["auz"] = permission
self.sdb.update(skey, "auz", permission)
_log_debug("response type: %s" % areq["response_type"])
@ -504,7 +512,7 @@ class Provider(object):
except KeyError:
pass
_log_debug("_dic: %s" % sinfo)
_log_debug("_dic: %s" % self.sdb[skey])
rtype = set(areq["response_type"][:])
if "code" in areq["response_type"]:
@ -512,19 +520,20 @@ class Provider(object):
# scode = self.sdb.duplicate(_sinfo)
# _sinfo = self.sdb[scode]
_code = aresp["code"] = self.sdb.get_token(sinfo)
_code = aresp["code"] = self.sdb.get_token(skey)
rtype.remove("code")
else:
sinfo["code"] = None
_code = None
_code = self.sdb[skey]["code"]
self.sdb.update(skey, "code", None)
if "token" in rtype:
_dic = self.sdb.upgrade_to_token(sinfo, issue_refresh=False)
self.sdb.upgrade_to_token(skey, issue_refresh=False,
access_grant=_code)
atr = AccessTokenResponse(**aresp.to_dict())
aresp = atr
_log_debug("_dic: %s" % _dic)
for key, val in _dic.items():
_cont = self.sdb[skey]
_log_debug("_dic: %s" % _cont)
for key, val in _cont.items():
if key in aresp.parameters() and val is not None:
aresp[key] = val
@ -538,7 +547,7 @@ class Provider(object):
except (RedirectURIError, ParameterError), err:
return BadRequest("%s" % err)
self.sdb.store_session(sinfo)
#self.sdb.store_session(skey)
# so everything went well should set a SSO cookie
headers = [authn.create_cookie(user, typ="sso", ttl=self.sso_ttl)]
@ -577,7 +586,14 @@ class Provider(object):
LOG_DEBUG("AccessTokenRequest: %s" % areq)
assert areq["grant_type"] == "authorization_code"
try:
assert areq["grant_type"] == "authorization_code"
except AssertionError:
err = TokenErrorResponse(error="invalid_request",
error_description="Wrong grant type")
return Response(err.to_json(), content="application/json",
status="401 Unauthorized")
# assert that the code is valid
_info = _sdb[areq["code"]]
@ -591,7 +607,14 @@ class Provider(object):
if "redirect_uri" in _info:
assert areq["redirect_uri"] == _info["redirect_uri"]
_tinfo = _sdb.update_to_token(areq["code"])
try:
_tinfo = _sdb.upgrade_to_token(areq["code"])
except AccessCodeUsed:
err = TokenErrorResponse(error="invalid_grant",
error_description="Access grant used")
return Response(err.to_json(), content="application/json",
status="401 Unauthorized")
LOG_DEBUG("_tinfo: %s" % _tinfo)

View File

@ -39,7 +39,9 @@ from oic.oauth2 import HTTP_ARGS
from oic.oauth2 import rndstr
from oic.oauth2.consumer import ConfigurationError
from oic.oauth2.exception import AccessDenied, PyoidcError, MissingParameter
from oic.exception import AccessDenied
from oic.exception import PyoidcError
from oic.exception import MissingParameter
from oic.utils import time_util
@ -904,10 +906,14 @@ class Client(oauth2.Client):
self.behaviour[_pref] = None
continue
for val in vals:
if val in _pvals:
self.behaviour[_pref] = val
break
if isinstance(vals, basestring):
if vals in _pvals:
self.behaviour[_pref] = vals
else:
for val in vals:
if val in _pvals:
self.behaviour[_pref] = val
break
if _pref not in self.behaviour:
raise ConfigurationError(

View File

@ -1,6 +1,5 @@
#!/usr/bin/env python
import logging
from oic.oauth2.exception import PyoidcError
__author__ = 'rohe0002'
@ -9,12 +8,12 @@ import os.path
from hashlib import md5
from oic.exception import PyoidcError
from oic.utils import http_util
from oic.oic import Client
from oic.oic import ENDPOINTS
from oic.oic.message import Claims, ClaimsRequest
from oic.oic.message import AuthorizationRequest
from oic.oic.message import AuthorizationResponse

View File

@ -1,6 +1,5 @@
import time
from urlparse import urlparse
from oic.oauth2.exception import InvalidRequest, PyoidcError
__author__ = 'rohe0002'
@ -11,6 +10,8 @@ import logging
from oic.oauth2 import message, MissingRequiredValue
from oic.oauth2 import MissingRequiredAttribute
from oic.oauth2 import VerificationError
from oic.exception import InvalidRequest
from oic.exception import PyoidcError
from oic.oauth2.message import Message, REQUIRED_LIST_OF_SP_SEP_STRINGS
from oic.oauth2.message import SINGLE_OPTIONAL_STRING
from oic.oauth2.message import OPTIONAL_LIST_OF_STRINGS

View File

@ -14,7 +14,6 @@ from oic.utils.keyio import key_export
from requests import ConnectionError
from oic.oauth2.message import by_schema
from oic.oauth2.message import MessageException
from oic.oic.message import RefreshAccessTokenRequest
from oic.oic.message import AuthorizationRequest, Claims
from oic.oic.message import IdToken
@ -58,7 +57,7 @@ from oic.oauth2 import rndstr
from oic.oic import Server
from oic.oauth2.exception import *
from oic.exception import *
logger = logging.getLogger(__name__)
@ -106,7 +105,7 @@ def code_token_response(**kwargs):
aresp["code"] = _scode
_dic = _sdb.update_to_token(_scode, issue_refresh=False)
_dic = _sdb.upgrade_to_token(_scode, issue_refresh=False)
for prop in AccessTokenResponse.c_param.keys():
try:
aresp[prop] = _dic[prop]
@ -441,13 +440,32 @@ class Provider(AProvider):
return Response("", headers=[authn.delete_cookie()])
def verify_endpoint(self, request="", cookie=None, **kwargs):
_req = urlparse.parse_qs(request)
try:
areq = urlparse.parse_qs(_req["query"][0])
except KeyError:
return BadRequest()
"""
:param request:
:param cookie:
:param kwargs:
:return:
"""
logger.debug("verify request: %s" % request)
_req = urlparse.parse_qs(request)
if "query" in _req:
try:
# TODO FIX THIS !!! Why query ?
areq = urlparse.parse_qs(_req["query"][0])
except KeyError:
return BadRequest()
else:
areq = _req
logger.debug("REQ: %s" % areq)
try:
authn, acr = self.pick_auth(areq, "exact")
except Exception, err:
logger.exception("%s", err)
raise
authn, acr = self.pick_auth(areq, "exact")
kwargs["cookie"] = cookie
return authn.verify(_req, **kwargs)
@ -665,7 +683,7 @@ class Provider(AProvider):
_log_debug("All checks OK")
try:
_tinfo = _sdb.update_to_token(_access_code)
_tinfo = _sdb.upgrade_to_token(_access_code)
except Exception, err:
logger.error("%s" % err)
# Should revoke the token issued to this access code
@ -1348,7 +1366,7 @@ class Provider(AProvider):
_code = None
if "token" in rtype:
_dic = self.sdb.update_to_token(issue_refresh=False, key=sid)
_dic = self.sdb.upgrade_to_token(issue_refresh=False, key=sid)
_log_debug("_dic: %s" % _dic)
for key, val in _dic.items():

View File

@ -2,8 +2,8 @@ import logging
from jwkest import Invalid
from jwkest import MissingKey
from jwkest.jws import alg2keytype
from oic.oauth2.exception import UnknownAssertionType
from oic.oauth2.exception import NotForMe
from oic.exception import UnknownAssertionType
from oic.exception import NotForMe
from oic.oauth2 import rndstr, VREQUIRED
from oic.oauth2 import SINGLE_OPTIONAL_STRING
from oic.oic import REQUEST2ENDPOINT
@ -61,7 +61,13 @@ class ClientSecretBasic(ClientAuthnMethod):
Section 3.2.1 of OAuth 2.0 [RFC6749] using HTTP Basic authentication scheme.
"""
def construct(self, cis, request_args=None, http_args=None, **kwargs):
# Basic HTTP Authentication
"""
:param cis: Request class instance
:param request_args: Request arguments
:param http_args: HTTP arguments
:return: dictionary of HTTP arguments
"""
if http_args is None:
http_args = {}
@ -89,7 +95,10 @@ class ClientSecretBasic(ClientAuthnMethod):
pass
if not cis.c_param["client_id"][VREQUIRED]:
del cis["client_id"]
try:
del cis["client_id"]
except KeyError:
pass
return http_args
@ -179,6 +188,20 @@ class BearerHeader(ClientAuthnMethod):
return http_args
def verify(self, environ, **kwargs):
try:
cred = environ["HTTP_AUTHORIZATION"]
except KeyError:
raise AuthnFailure("missing authorization info")
try:
assert cred.startswith("Bearer ")
except AssertionError:
raise AuthnFailure("Wrong type of authorization token")
label, token = cred.split(" ")
return token
class BearerBody(ClientAuthnMethod):
def construct(self, cis, request_args=None, http_args=None, **kwargs):

View File

@ -1,5 +1,5 @@
from oic.oauth2 import rndstr
from oic.oauth2.exception import UnsupportedMethod
from oic.exception import UnsupportedMethod
from oic.utils.aes import encrypt
from oic.utils.aes import decrypt
@ -58,6 +58,18 @@ class Created(Response):
_status = "201 Created"
class Accepted(Response):
_status = "202 Accepted"
class NonAuthoritativeInformation(Response):
_status = "203 Non Authoritative Information"
class NoContent(Response):
_status = "204 No Content"
class Redirect(Response):
_template = '<html>\n<head><title>Redirecting to %s</title></head>\n' \
'<body>\nYou are being redirected to <a href="%s">%s</a>\n' \
@ -103,6 +115,10 @@ class NotFound(Response):
_status = '404 NOT FOUND'
class NotSupported(Response):
_status = '405 Not Support'
class NotAcceptable(Response):
_status = '406 Not Acceptable'
@ -118,19 +134,23 @@ class InvalidCookieSign(Exception):
R2C = {
200: Response,
201: Created,
202: Accepted,
203: NonAuthoritativeInformation,
204: NoContent,
302: Redirect,
303: SeeOther,
400: BadRequest,
401: Unauthorized,
403: Forbidden,
404: NotFound,
405: NotSupported,
406: NotAcceptable,
500: ServiceError,
}
def factory(code, message):
return R2C[code](message)
def factory(code, message, **kwargs):
return R2C[code](message, **kwargs)
def extract(environ, empty=False, err=False):

View File

@ -1,6 +1,7 @@
import json
import time
from Crypto.PublicKey import RSA
from oic.exception import MessageException
__author__ = 'rohe0002'
@ -489,7 +490,11 @@ class KeyJar(object):
"""
logger.debug("loading keys for issuer: %s" % issuer)
logger.debug("pcr: %s" % pcr)
try:
logger.debug("pcr: %s" % pcr)
except MessageException:
pass
if issuer not in self.issuer_keys:
self.issuer_keys[issuer] = []
elif replace:

View File

@ -26,6 +26,10 @@ class WrongTokenType(Exception):
pass
class AccessCodeUsed(Exception):
pass
def pairwise_id(sub, sector_identifier, seed):
return hashlib.sha256("%s%s%s" % (sub, sector_identifier, seed)).hexdigest()
@ -245,8 +249,14 @@ class SessionDB(object):
self.uid2sid[sub] = sid
return sid
def update_to_token(self, token=None, issue_refresh=True, id_token="",
oidreq=None, key=None):
def get_token(self, key):
if self._db[key]["oauth_state"] == "authz":
return self._db[key]["code"]
elif self._db[key]["oauth_state"] == "token":
return self._db[key]["access_token"]
def upgrade_to_token(self, token=None, issue_refresh=True, id_token="",
oidreq=None, key=None, access_grant=""):
"""
:param token: The access grant
@ -257,7 +267,11 @@ class SessionDB(object):
:return: The session information as a dictionary
"""
if token:
(typ, key) = self.token.type_and_key(token)
try:
(typ, key) = self.token.type_and_key(token)
except (ValueError, TypeError):
(typ, key) = self.token.type_and_key(access_grant)
token = access_grant
if typ != "A": # not a access grant
raise WrongTokenType("Not a grant token")
@ -265,7 +279,7 @@ class SessionDB(object):
dic = self._db[key]
if dic["code_used"]:
raise Exception("Access code already used!!")
raise AccessCodeUsed()
_at = self.token("T", token)
dic["code_used"] = True
else:

View File

@ -54,34 +54,6 @@ class StateLess(object):
#return _cont.to_jwe(self.keys, self.enc, self.alg)
return _cont
#def update_to_token(self, token=None, issue_refresh=True, **kwargs):
# """
#
# :param token: The access grant
# :param issue_refresh: If a refresh token should be issued
# :return: A new token
# """
# if token in self.used_grants:
# raise Exception("Grant already used")
#
# _cont = Content().from_jwe(token, self.keys)
#
# try:
# assert _cont["typ"] == "code"
# except AssertionError:
# raise Exception("Not a access grant")
#
# self.used_grants.append(token)
#
# _cont["typ"] = "access"
# _cont["val"] = epoch_in_a_while(self.validity["access"])
# if issue_refresh:
# _c = Content(sub=_cont["sub"], aud=_cont["aud"], typ="refresh",
# val=epoch_in_a_while(self.validity["refresh"]))
# _cont["ref"] = _c.to_jwe(self.keys, self.enc, self.alg)
#
# return _cont.to_jwe(self.keys, self.enc, self.alg)
def upgrade_to_token(self, cont, issue_refresh=False):
cont["typ"] = "access"
cont["val"] = epoch_in_a_while(self.validity["access"])

View File

@ -62,7 +62,7 @@ class MyFakeOAuth2Server(Server):
if "code" in req["response_type"]:
if "token" in req["response_type"]:
grant = _info["code"]
_dict = self.sdb.update_to_token(grant)
_dict = self.sdb.upgrade_to_token(grant)
_dict["oauth_state"]="authz",
_dict = by_schema(AuthorizationResponse(), **_dict)
@ -77,7 +77,7 @@ class MyFakeOAuth2Server(Server):
params = AccessTokenResponse.c_param.keys()
_dict = dict([(k,v) for k,
v in self.sdb.update_to_token(grant).items() if k in
v in self.sdb.upgrade_to_token(grant).items() if k in
params])
try:
del _dict["refresh_token"]

View File

@ -103,7 +103,7 @@ class MyFakeOICServer(Server):
if "code" in req["response_type"]:
if "token" in req["response_type"]:
grant = _info["code"]
_dict = self.sdb.update_to_token(grant)
_dict = self.sdb.upgrade_to_token(grant)
_dict["oauth_state"] = "authz",
_dict = by_schema(AuthorizationResponse(), **_dict)
@ -118,7 +118,7 @@ class MyFakeOICServer(Server):
params = AccessTokenResponse.c_param.keys()
_dict = dict([(k, v) for k, v in
self.sdb.update_to_token(grant).items() if k in
self.sdb.upgrade_to_token(grant).items() if k in
params])
try:
del _dict["refresh_token"]
@ -148,7 +148,7 @@ class MyFakeOICServer(Server):
_info = self.sdb.refresh_token(req["refresh_token"])
elif "grant_type=authorization_code":
req = self.parse_token_request(body=data)
_info = self.sdb.update_to_token(req["code"])
_info = self.sdb.upgrade_to_token(req["code"])
else:
response = TokenErrorResponse(error="unsupported_grant_type")
return response, ""
@ -179,7 +179,10 @@ class MyFakeOICServer(Server):
return response
def registration_endpoint(self, data):
req = self.parse_registration_request(data)
try:
req = self.parse_registration_request(data, "json")
except ValueError:
req = self.parse_registration_request(data)
client_secret = rndstr()
expires = utc_time_sans_frac() + self.registration_expires_in

View File

@ -959,4 +959,4 @@ def test_bearer_body_get_token():
assert cis["access_token"] == "token1"
if __name__ == "__main__":
test_server_parse_jwt_request()
test_client_secret_basic()

View File

@ -1,10 +1,9 @@
from mako.lookup import TemplateLookup
from mako.runtime import UNDEFINED
from oic.oauth2 import rndstr
from oic.utils.authn.authn_context import AuthnBroker
from oic.utils.authn.client import verify_client
from oic.utils.authn.user import UserAuthnMethod
from oic.utils.authz import AuthzHandling, Implicit
from oic.utils.authz import Implicit
from oic.utils.http_util import Response
from oic.oauth2.message import AuthorizationRequest
@ -270,4 +269,4 @@ def test_token_endpoint_unauth():
assert _eq(atr.keys(), ['error_description', 'error'])
if __name__ == "__main__":
test_provider_authenticated()
test_provider_authenticated_token()

View File

@ -548,6 +548,7 @@ def test_client_register():
if __name__ == "__main__":
t = TestOICConsumer()
t.setup_class()
t.test_begin()
#t = TestOICConsumer()
#t.setup_class()
#t.test_begin()
test_client_register()

View File

@ -6,7 +6,7 @@ from oic.utils.authn.user import UserAuthnMethod
from oic.utils.authz import AuthzHandling
from oic.utils.userinfo import UserInfo
from oic.oauth2.exception import RedirectURIError
from oic.exception import RedirectURIError
from oic.utils.keyio import KeyBundle
from oic.utils.keyio import KeyJar
@ -680,4 +680,4 @@ def test_registered_redirect_uri_with_query_component():
assert resp is None
if __name__ == "__main__":
test_userinfo_endpoint()
test_token_endpoint()

View File

@ -166,11 +166,11 @@ def test_create_authz_session_with_sector_id():
assert info_2["sub"] != user_id1
def test_update_to_token():
def test_upgrade_to_token():
sdb = SessionDB()
sid = sdb.create_authz_session("user_id", AREQ)
grant = sdb[sid]["code"]
_dict = sdb.update_to_token(grant)
_dict = sdb.upgrade_to_token(grant)
print _dict.keys()
assert _eq(_dict.keys(), ['code', 'authzreq', 'token_type', 'local_sub',
@ -180,15 +180,15 @@ def test_update_to_token():
'redirect_uri', 'code_used', 'scope',
'access_token_scope'])
raises(Exception, 'sdb.update_to_token(grant)')
raises(Exception, 'sdb.upgrade_to_token(grant)')
raises(Exception, 'sdb.update_to_token(_dict["access_token"]')
raises(Exception, 'sdb.upgrade_to_token(_dict["access_token"]')
sdb = SessionDB()
sid = sdb.create_authz_session("another_user_id", AREQ)
grant = sdb[sid]["code"]
_dict = sdb.update_to_token(grant, id_token="id_token", oidreq=OIDR)
_dict = sdb.upgrade_to_token(grant, id_token="id_token", oidreq=OIDR)
print _dict.keys()
assert _eq(_dict.keys(), ['code', 'authzreq', 'id_token', 'token_type',
'local_sub', 'client_id', 'oauth_state',
@ -200,14 +200,14 @@ def test_update_to_token():
assert _dict["id_token"] == "id_token"
assert _dict["oidreq"].type() == "OpenIDRequest"
_ = _dict["access_token"]
raises(Exception, 'sdb.update_to_token(token)')
raises(Exception, 'sdb.upgrade_to_token(token)')
def test_refresh_token():
sdb = SessionDB()
sid = sdb.create_authz_session("user_id", AREQ)
grant = sdb[sid]["code"]
_dict = sdb.update_to_token(grant)
_dict = sdb.upgrade_to_token(grant)
dict1 = _dict.copy()
rtoken = _dict["refresh_token"]
@ -228,7 +228,7 @@ def test_is_valid():
assert sdb.is_valid(grant)
_dict = sdb.update_to_token(grant)
_dict = sdb.upgrade_to_token(grant)
assert sdb.is_valid(grant) is False
token1 = _dict["access_token"]
assert sdb.is_valid(token1)
@ -268,7 +268,7 @@ def test_revoke_token():
sid = sdb.create_authz_session("user_id", AREQ)
grant = sdb[sid]["code"]
_dict = sdb.update_to_token(grant)
_dict = sdb.upgrade_to_token(grant)
token = _dict["access_token"]
rtoken = _dict["refresh_token"]

View File

@ -12,7 +12,7 @@ def test_access_code():
st = StateLess(keys, enc_alg="A128KW", enc_method="A128CBC-HS256")
con = st.create_authz_session("subject",
{"redirect_uri": "https://example.com"})
tok = st.encrypt(con)
tok = st.get_token(con)
_info = st[tok]
print _info

324
tests/test_x_dynreg.py Normal file
View File

@ -0,0 +1,324 @@
from mako.lookup import TemplateLookup
from oic.utils.http_util import Response, NoContent, Unauthorized
from oic.utils.authn.authn_context import AuthnBroker
from oic.utils.authn.client import verify_client
from oic.utils.authn.client import BearerHeader
from oic.utils.authn.client import ClientSecretPost
from oic.utils.authn.client import ClientSecretBasic
from oic.utils.authn.user import UserAuthnMethod
from oic.utils.authz import Implicit
from oic.utils import sdb
from oic.oauth2.dynreg import Provider
from oic.oauth2.dynreg import RegistrationRequest
from oic.oauth2.dynreg import ClientInfoResponse
from oic.oauth2.dynreg import ClientRegistrationError
CLIENT_CONFIG = {
"client_id": "client1",
"ca_certs": "/usr/local/etc/oic/ca_certs.txt",
}
CONSUMER_CONFIG = {
"authz_page": "/authz",
"flow_type": "code",
#"password": args.passwd,
"scope": [],
"response_type": "code",
#"expire_in": 600,
}
SERVER_INFO = {
"version": "3.0",
"issuer": "https://connect-op.heroku.com",
"authorization_endpoint": "http://localhost:8088/authorization",
"token_endpoint": "http://localhost:8088/token",
#"userinfo_endpoint":"http://localhost:8088/user_info",
#"check_id_endpoint":"http://localhost:8088/id_token",
#"registration_endpoint":"https://connect-op.heroku.com/connect/client",
#"scopes_supported":["openid","profile","email","address","PPID"],
"flows_supported": ["code", "token", "code token"],
#"identifiers_supported":["public","ppid"],
#"x509_url":"https://connect-op.heroku.com/cert.pem"
}
CDB = {
"a1b2c3": {
"password": "hemligt",
"client_secret": "drickyoughurt"
},
"client1": {
"client_secret": "hemlighet",
"redirect_uris": [("http://localhost:8087/authz", None)]
}
}
PASSWD = {"user": "password"}
ROOT = '../oc3/'
tl = TemplateLookup(directories=[ROOT + 'templates', ROOT + 'htdocs'],
module_directory=ROOT + 'modules',
input_encoding='utf-8', output_encoding='utf-8')
class DummyAuthn(UserAuthnMethod):
def __init__(self, srv, user):
UserAuthnMethod.__init__(self, srv)
self.user = user
def authenticated_as(self, cookie=None, **kwargs):
return {"uid": self.user}
AUTHN_BROKER = AuthnBroker()
AUTHN_BROKER.add("UNDEFINED", DummyAuthn(None, "username"))
# dealing with authorization
AUTHZ = Implicit()
def content_type(headers):
for key, val in headers:
if key == "Content-type":
if val == "application/json":
return "json"
def _eq(l1, l2):
return set(l1) == set(l2)
def test_provider_init():
provider = Provider("pyoicserv", sdb.SessionDB(), CDB, AUTHN_BROKER, AUTHZ,
verify_client, client_info_url="https://example.com/as")
assert provider
def test_client_registration():
provider = Provider("pyoicserv", sdb.SessionDB(), CDB, AUTHN_BROKER, AUTHZ,
verify_client,
client_info_url="https://example.com/as/")
request = RegistrationRequest(client_name="myself",
redirect_uris=["https://example.com/rp"])
resp = provider.registration_endpoint(request.to_json(), {})
assert isinstance(resp, Response)
_resp = ClientInfoResponse().from_json(resp.message)
assert "client_id" in _resp
def test_client_registration_uri_error():
args = {
"redirect_uris": ["https://client.example.org/callback",
"https://client.example.org/callback2"],
"client_name": "My Example Client",
"client_name#ja-Jpan-JP":
"\u30AF\u30E9\u30A4\u30A2\u30F3\u30C8\u540D",
"token_endpoint_auth_method": "client_secret_basic",
"scope": "read write dolphin",
"logo_uri": "https://client.example.org/logo.png",
"jwks_uri": "https://client.example.org/my_public_keys.jwks"
}
provider = Provider("pyoicserv", sdb.SessionDB(), CDB, AUTHN_BROKER, AUTHZ,
verify_client,
client_info_url="https://example.com/as/")
request = RegistrationRequest(**args)
resp = provider.registration_endpoint(request.to_json(), {})
assert isinstance(resp, Response)
_resp = ClientRegistrationError().from_json(resp.message)
assert "error" in _resp
assert _resp["error"] == "invalid_client_metadata"
def test_client_registration_2():
args = {
"redirect_uris": ["https://client.example.org/callback",
"https://client.example.org/callback2"],
"client_name": "My Example Client",
"client_name#ja-Jpan-JP":
"\u30AF\u30E9\u30A4\u30A2\u30F3\u30C8\u540D",
"token_endpoint_auth_method": "client_secret_basic",
"scope": "read write dolphin",
}
provider = Provider("pyoicserv", sdb.SessionDB(), CDB, AUTHN_BROKER, AUTHZ,
verify_client,
client_info_url="https://example.com/as/",
client_authn_methods={
"client_secret_post": ClientSecretPost,
"client_secret_basic": ClientSecretBasic,
"bearer_header": BearerHeader})
request = RegistrationRequest(**args)
resp = provider.registration_endpoint(request.to_json(), {})
assert isinstance(resp, Response)
_resp = ClientInfoResponse().from_json(resp.message)
assert "client_name#ja-Jpan-JP" in _resp.keys()
assert "client_name" in _resp.keys()
def test_client_user_info_get():
args = {
"redirect_uris": ["https://client.example.org/callback",
"https://client.example.org/callback2"],
"client_name": "My Example Client",
"client_name#ja-Jpan-JP":
"\u30AF\u30E9\u30A4\u30A2\u30F3\u30C8\u540D",
"token_endpoint_auth_method": "client_secret_basic",
"scope": "read write dolphin",
}
provider = Provider("pyoicserv", sdb.SessionDB(), CDB, AUTHN_BROKER, AUTHZ,
verify_client,
client_info_url="https://example.com/as/",
client_authn_methods={
"client_secret_post": ClientSecretPost,
"client_secret_basic": ClientSecretBasic,
"bearer_header": BearerHeader})
request = RegistrationRequest(**args)
resp = provider.registration_endpoint(request.to_json(),
environ={})
assert isinstance(resp, Response)
_resp = ClientInfoResponse().from_json(resp.message)
assert "client_name#ja-Jpan-JP" in _resp.keys()
assert "client_name" in _resp.keys()
resp = provider.client_info_endpoint(
"",
environ={"HTTP_AUTHORIZATION": "Bearer %s" % (
_resp["registration_access_token"],)},
query="client_id=%s" % _resp["client_id"])
_resp_cir = ClientInfoResponse().from_json(resp.message)
assert _resp == _resp_cir
def test_client_registration_update():
args = {
"redirect_uris": ["https://client.example.org/callback",
"https://client.example.org/callback2"],
"client_name": "My Example Client",
"client_name#ja-Jpan-JP":
"\u30AF\u30E9\u30A4\u30A2\u30F3\u30C8\u540D",
"token_endpoint_auth_method": "client_secret_basic",
"scope": "read write dolphin",
}
provider = Provider("pyoicserv", sdb.SessionDB(), CDB, AUTHN_BROKER, AUTHZ,
verify_client,
client_info_url="https://example.com/as/",
client_authn_methods={
"client_secret_post": ClientSecretPost,
"client_secret_basic": ClientSecretBasic,
"bearer_header": BearerHeader})
request = RegistrationRequest(**args)
resp = provider.registration_endpoint(request.to_json(),
environ={})
assert isinstance(resp, Response)
_resp = ClientInfoResponse().from_json(resp.message)
assert "client_name#ja-Jpan-JP" in _resp.keys()
assert "client_name" in _resp.keys()
update = {
"client_id": _resp["client_id"],
"client_secret": _resp["client_secret"],
"redirect_uris": ["https://client.example.org/callback",
"https://client.example.org/alt"],
"scope": "read write dolphin",
"grant_types": ["authorization_code", "refresh_token"],
"token_endpoint_auth_method": "client_secret_basic",
"jwks_uri": "https://client.example.org/my_public_keys.jwks",
"client_name": "My New Example",
"client_name#fr": "Mon Nouvel Exemple",
}
update_req = RegistrationRequest(**update)
resp = provider.client_info_endpoint(
update_req.to_json(),
environ={"HTTP_AUTHORIZATION": "Bearer %s" % (
_resp["registration_access_token"],)},
method="PUT",
query="client_id=%s" % _resp["client_id"])
_resp_up = ClientInfoResponse().from_json(resp.message)
print _resp_up
def test_client_registration_delete():
args = {
"redirect_uris": ["https://client.example.org/callback",
"https://client.example.org/callback2"],
"client_name": "My Example Client",
"client_name#ja-Jpan-JP":
"\u30AF\u30E9\u30A4\u30A2\u30F3\u30C8\u540D",
"token_endpoint_auth_method": "client_secret_basic",
"scope": "read write dolphin",
}
provider = Provider("pyoicserv", sdb.SessionDB(), CDB, AUTHN_BROKER, AUTHZ,
verify_client,
client_info_url="https://example.com/as/",
client_authn_methods={
"client_secret_post": ClientSecretPost,
"client_secret_basic": ClientSecretBasic,
"bearer_header": BearerHeader})
request = RegistrationRequest(**args)
resp = provider.registration_endpoint(request.to_json(),
environ={})
assert isinstance(resp, Response)
_resp = ClientInfoResponse().from_json(resp.message)
resp = provider.client_info_endpoint(
"",
environ={"HTTP_AUTHORIZATION": "Bearer %s" % (
_resp["registration_access_token"],)},
method="DELETE",
query="client_id=%s" % _resp["client_id"])
assert isinstance(resp, NoContent)
# A read should fail
resp = provider.client_info_endpoint(
"",
environ={"HTTP_AUTHORIZATION": "Bearer %s" % (
_resp["registration_access_token"],)},
query="client_id=%s" % _resp["client_id"])
assert isinstance(resp, Unauthorized)
# -----------------------------------------------------------------------------
test_client_registration_delete()