Skip to content

Commit

Permalink
Merge pull request #83 from IdentityPython/ia0
Browse files Browse the repository at this point in the history
Identity Assurance support has been out in the cold. Time to bring it in again.
  • Loading branch information
rohe authored Nov 23, 2023
2 parents 25c1a27 + 3d1aee7 commit 7364f05
Show file tree
Hide file tree
Showing 99 changed files with 1,487 additions and 1,066 deletions.
2 changes: 1 addition & 1 deletion demo/oauth2_add_on_dpop.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from common import KEYDEFS
from common import full_path
from flow import Flow
from idpyoidc.claims import get_signing_algs
from idpyoidc.metadata import get_signing_algs
from idpyoidc.client.oauth2 import Client
from idpyoidc.server import Server
from idpyoidc.server.configure import ASConfiguration
Expand Down
2 changes: 1 addition & 1 deletion demo/oidc_add_on_dpop.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from common import KEYDEFS
from common import full_path
from flow import Flow
from idpyoidc.claims import get_signing_algs
from idpyoidc.metadata import get_signing_algs
from idpyoidc.client.oauth2 import Client
from idpyoidc.server import Server
from idpyoidc.server.configure import ASConfiguration
Expand Down
2 changes: 1 addition & 1 deletion example/flask_op/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"server_info": {
"add_on": {
"pkce": {
"function": "idpyoidc.server.oidc.add_on.pkce.add_pkce_support",
"function": "idpyoidc.server.oauth2.add_on.pkce.add_support",
"kwargs": {
"essential": false,
"code_challenge_method": "S256 S384 S512"
Expand Down
2 changes: 1 addition & 1 deletion src/idpyoidc/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
__author__ = "Roland Hedberg"
__version__ = "2.1.0"
__version__ = "2.2.0"

VERIFIED_CLAIM_PREFIX = "__verified"

Expand Down
42 changes: 0 additions & 42 deletions src/idpyoidc/claims.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
from functools import cmp_to_key
from typing import Callable
from typing import Optional

from cryptojwt import KeyJar
from cryptojwt.jwe import SUPPORTED
from cryptojwt.jws.jws import SIGNER_ALGS
from cryptojwt.key_jar import init_key_jar
from cryptojwt.utils import importer

Expand Down Expand Up @@ -215,42 +212,3 @@ def get_claim(self, key, default=None):
return default
else:
return _val


SIGNING_ALGORITHM_SORT_ORDER = ["RS", "ES", "PS", "HS"]


def cmp(a, b):
return (a > b) - (a < b)


def alg_cmp(a, b):
if a == "none":
return 1
elif b == "none":
return -1

_pos1 = SIGNING_ALGORITHM_SORT_ORDER.index(a[0:2])
_pos2 = SIGNING_ALGORITHM_SORT_ORDER.index(b[0:2])
if _pos1 == _pos2:
return (a > b) - (a < b)
elif _pos1 > _pos2:
return 1
else:
return -1


def get_signing_algs():
# Assumes Cryptojwt
_list = list(SIGNER_ALGS.keys())
# know how to do none but should not
_list.remove("none")
return sorted(_list, key=cmp_to_key(alg_cmp))


def get_encryption_algs():
return SUPPORTED["alg"]


def get_encryption_encs():
return SUPPORTED["enc"]
8 changes: 4 additions & 4 deletions src/idpyoidc/client/claims/oidc.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import os
from typing import Optional

from idpyoidc import claims
from idpyoidc import metadata
from idpyoidc.client import claims as client_claims
from idpyoidc.client.claims.transform import create_registration_request
from idpyoidc.message.oidc import RegistrationRequest
Expand Down Expand Up @@ -75,9 +75,9 @@ class Claims(client_claims.Claims):
"encrypt_id_token_supported": None,
# "grant_types_supported": ["authorization_code", "refresh_token"],
"logo_uri": None,
"id_token_signing_alg_values_supported": claims.get_signing_algs,
"id_token_encryption_alg_values_supported": claims.get_encryption_algs,
"id_token_encryption_enc_values_supported": claims.get_encryption_encs,
"id_token_signing_alg_values_supported": metadata.get_signing_algs,
"id_token_encryption_alg_values_supported": metadata.get_encryption_algs,
"id_token_encryption_enc_values_supported": metadata.get_encryption_encs,
"initiate_login_uri": None,
"jwks": None,
"jwks_uri": None,
Expand Down
5 changes: 3 additions & 2 deletions src/idpyoidc/client/client_auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@

from idpyoidc.defaults import DEF_SIGN_ALG
from idpyoidc.defaults import JWT_BEARER
from idpyoidc.message.oauth2 import AccessTokenRequest
from idpyoidc.message.oauth2 import SINGLE_OPTIONAL_STRING
from idpyoidc.message.oauth2 import AccessTokenRequest
from idpyoidc.message.oidc import AuthnToken
from idpyoidc.time_util import utc_time_sans_frac
from idpyoidc.util import rndstr
from .util import sanitize

from ..message import VREQUIRED
from ..util import instantiate
from .util import sanitize

# from idpyoidc.oidc.backchannel_authentication import ClientNotificationAuthn

Expand Down
1 change: 1 addition & 0 deletions src/idpyoidc/client/configure.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

from idpyoidc.configure import Base
from idpyoidc.logging import configure_logging

from .util import lower_or_upper

try:
Expand Down
1 change: 1 addition & 0 deletions src/idpyoidc/client/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ def __init__(
keyjar=self.keyjar,
upstream_get=self.unit_get,
client_type=client_type,
entity_id=self.entity_id,
)

self.setup_client_authn_methods(config)
Expand Down
2 changes: 1 addition & 1 deletion src/idpyoidc/client/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
from http.cookies import CookieError
from http.cookies import SimpleCookie

from requests import request
from idpyoidc.client.exception import NonFatalException
from idpyoidc.client.util import sanitize
from idpyoidc.client.util import set_cookie
from requests import request

__author__ = "roland"

Expand Down
91 changes: 47 additions & 44 deletions src/idpyoidc/client/oauth2/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,22 @@
from typing import Union

from cryptojwt.key_jar import KeyJar
from requests import request

from idpyoidc.client.entity import Entity
from idpyoidc.client.exception import ConfigurationError
from idpyoidc.client.exception import OidcServiceError
from idpyoidc.client.exception import ParseError
from idpyoidc.client.service import REQUEST_INFO
from idpyoidc.client.service import Service
from idpyoidc.client.service import SUCCESSFUL
from idpyoidc.client.service import Service
from idpyoidc.client.util import do_add_ons
from idpyoidc.client.util import get_deserialization_method
from idpyoidc.configure import Configuration
from idpyoidc.context import OidcContext
from idpyoidc.exception import FormatError
from idpyoidc.message import Message
from idpyoidc.message.oauth2 import is_error_message
from requests import request

__author__ = "Roland Hedberg"

Expand All @@ -38,20 +38,20 @@ class Client(Entity):
client_type = "oauth2"

def __init__(
self,
keyjar: Optional[KeyJar] = None,
config: Optional[Union[dict, Configuration]] = None,
services: Optional[dict] = None,
httpc: Optional[Callable] = None,
httpc_params: Optional[dict] = None,
context: Optional[OidcContext] = None,
upstream_get: Optional[Callable] = None,
key_conf: Optional[dict] = None,
entity_id: Optional[str] = "",
verify_ssl: Optional[bool] = True,
jwks_uri: Optional[str] = "",
client_type: Optional[str] = "",
**kwargs
self,
keyjar: Optional[KeyJar] = None,
config: Optional[Union[dict, Configuration]] = None,
services: Optional[dict] = None,
httpc: Optional[Callable] = None,
httpc_params: Optional[dict] = None,
context: Optional[OidcContext] = None,
upstream_get: Optional[Callable] = None,
key_conf: Optional[dict] = None,
entity_id: Optional[str] = "",
verify_ssl: Optional[bool] = True,
jwks_uri: Optional[str] = "",
client_type: Optional[str] = "",
**kwargs
):
"""
Expand All @@ -68,9 +68,12 @@ def __init__(
:return: Client instance
"""

if config is None:
config = {}

if client_type:
self.client_type = client_type
elif config and 'client_type' in config:
elif config and "client_type" in config:
client_type = self.client_type = config["client_type"]
else:
client_type = self.client_type
Expand All @@ -82,7 +85,7 @@ def __init__(
else:
httpc_params = {"verify": False}

jwks_uri = jwks_uri or config.get('jwks_uri', '')
jwks_uri = jwks_uri or config.get("jwks_uri", "")

Entity.__init__(
self,
Expand Down Expand Up @@ -110,12 +113,12 @@ def __init__(
do_add_ons(_add_ons, self._service)

def do_request(
self,
request_type: str,
response_body_type: Optional[str] = "",
request_args: Optional[dict] = None,
behaviour_args: Optional[dict] = None,
**kwargs
self,
request_type: str,
response_body_type: Optional[str] = "",
request_args: Optional[dict] = None,
behaviour_args: Optional[dict] = None,
**kwargs
):
_srv = self._service[request_type]

Expand All @@ -138,14 +141,14 @@ def set_client_id(self, client_id):
self.get_context().set("client_id", client_id)

def get_response(
self,
service: Service,
url: str,
method: Optional[str] = "GET",
body: Optional[dict] = None,
response_body_type: Optional[str] = "",
headers: Optional[dict] = None,
**kwargs
self,
service: Service,
url: str,
method: Optional[str] = "GET",
body: Optional[dict] = None,
response_body_type: Optional[str] = "",
headers: Optional[dict] = None,
**kwargs
):
"""
Expand Down Expand Up @@ -181,14 +184,14 @@ def get_response(
return self.parse_request_response(service, resp, response_body_type, **kwargs)

def service_request(
self,
service: Service,
url: str,
method: Optional[str] = "GET",
body: Optional[dict] = None,
response_body_type: Optional[str] = "",
headers: Optional[dict] = None,
**kwargs
self,
service: Service,
url: str,
method: Optional[str] = "GET",
body: Optional[dict] = None,
response_body_type: Optional[str] = "",
headers: Optional[dict] = None,
**kwargs
) -> Message:
"""
The method that sends the request and handles the response returned.
Expand Down Expand Up @@ -317,10 +320,10 @@ def dynamic_provider_info_discovery(client: Client, behaviour_args: Optional[dic
:param client: A :py:class:`idpyoidc.client.oidc.Client` instance
"""

if client.client_type == 'oidc' and client.get_service("provider_info"):
service = 'provider_info'
elif client.client_type == 'oauth2' and client.get_service('server_metadata'):
service = 'server_metadata'
if client.client_type == "oidc" and client.get_service("provider_info"):
service = "provider_info"
elif client.client_type == "oauth2" and client.get_service("server_metadata"):
service = "server_metadata"
else:
raise ConfigurationError("Can not do dynamic provider info discovery")

Expand Down
2 changes: 1 addition & 1 deletion src/idpyoidc/client/oauth2/access_token.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
from idpyoidc.client.service import Service
from idpyoidc.message import oauth2
from idpyoidc.message.oauth2 import ResponseMessage
from idpyoidc.metadata import get_signing_algs
from idpyoidc.time_util import time_sans_frac
from idpyoidc.claims import get_signing_algs

LOGGER = logging.getLogger(__name__)

Expand Down
4 changes: 1 addition & 3 deletions src/idpyoidc/client/oauth2/add_on/dpop.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,18 @@
from hashlib import sha256
from typing import Optional

from cryptography.hazmat.primitives import hashes
from cryptojwt.jwk.jwk import key_from_jwk_dict
from cryptojwt.jws.jws import JWS
from cryptojwt.jws.jws import factory
from cryptojwt.jws.jws import SIGNER_ALGS
from cryptojwt.key_bundle import key_by_alg

from idpyoidc.claims import get_signing_algs
from idpyoidc.client.service_context import ServiceContext
from idpyoidc.message import SINGLE_OPTIONAL_STRING
from idpyoidc.message import SINGLE_REQUIRED_INT
from idpyoidc.message import SINGLE_REQUIRED_JSON
from idpyoidc.message import SINGLE_REQUIRED_STRING
from idpyoidc.message import Message
from idpyoidc.metadata import get_signing_algs
from idpyoidc.time_util import utc_time_sans_frac

logger = logging.getLogger(__name__)
Expand Down
5 changes: 3 additions & 2 deletions src/idpyoidc/client/oauth2/add_on/jar.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from typing import Optional

from idpyoidc import claims
from idpyoidc import metadata
from idpyoidc.client.oidc.utils import construct_request_uri
from idpyoidc.client.oidc.utils import request_object_encryption
from idpyoidc.message.oidc import make_openid_request
Expand Down Expand Up @@ -207,8 +208,8 @@ def add_support(
args["request_dir"] = request_dir

if request_object_encryption_enc and request_object_encryption_alg:
if request_object_encryption_enc in claims.get_encryption_encs():
if request_object_encryption_alg in claims.get_encryption_algs():
if request_object_encryption_enc in metadata.get_encryption_encs():
if request_object_encryption_alg in metadata.get_encryption_algs():
args["request_object_encryption_enc"] = request_object_encryption_enc
args["request_object_encryption_alg"] = request_object_encryption_alg
else:
Expand Down
2 changes: 1 addition & 1 deletion src/idpyoidc/client/oauth2/add_on/par.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

from cryptojwt import JWT
from cryptojwt.utils import importer
from requests import request

from idpyoidc.client.client_auth import CLIENT_AUTHN_METHOD
from idpyoidc.message import Message
from idpyoidc.message.oauth2 import JWTSecuredAuthorizationRequest
from idpyoidc.util import instantiate
from requests import request

logger = logging.getLogger(__name__)

Expand Down
Loading

0 comments on commit 7364f05

Please sign in to comment.