Example #1
0
def test_verify_id_token_at_hash_and_chash():
    token = 'AccessTokenWhichCouldBeASignedJWT'
    at_hash = left_hash(token)
    code = 'AccessCode1'
    c_hash = left_hash(code)

    idt = IdToken(**{
        "sub": "553df2bcf909104751cfd8b2",
        "aud": [
            "5542958437706128204e0000",
            "554295ce3770612820620000"
            ],
        "auth_time": 1441364872,
        "azp": "554295ce3770612820620000",
        "at_hash": at_hash,
        'c_hash': c_hash
        })

    kj = KeyJar()
    kj.add_symmetric("", 'dYMmrcQksKaPkhdgRNYk3zzh5l7ewdDJ', ['sig'])
    kj.add_symmetric("https://sso.qa.7pass.ctf.prosiebensat1.com",
                     'dYMmrcQksKaPkhdgRNYk3zzh5l7ewdDJ', ['sig'])
    packer = JWT(kj, sign_alg='HS256',
                 iss="https://sso.qa.7pass.ctf.prosiebensat1.com",
                 lifetime=3600)
    _jws = packer.pack(**idt.to_dict())
    msg = AuthorizationResponse(access_token=token, id_token=_jws, code=code)
    verify_id_token(msg, check_hash=True, keyjar=kj,
                    iss="https://sso.qa.7pass.ctf.prosiebensat1.com",
                    client_id="554295ce3770612820620000")
Example #2
0
def verify_id_token(instance, check_hash=False, **kwargs):
    # Try to decode the JWT, checks the signature
    args = {}
    for arg in ["key", "keyjar", "algs", "sender"]:
        try:
            args[arg] = kwargs[arg]
        except KeyError:
            pass

    _jws = str(instance["id_token"])

    # It can be encrypted, so try to decrypt first
    _jwe = JWE_factory(_jws)
    if _jwe is not None:
        try:
            _jws = _jwe.decrypt(keys=kwargs["keyjar"].get_decrypt_key())
        except JWEException as err:
            raise VerificationError("Could not decrypt id_token", err)
    _packer = JWT()
    _body = _packer.unpack(_jws).payload()

    if "keyjar" in kwargs:
        try:
            if _body["iss"] not in kwargs["keyjar"]:
                raise ValueError("Unknown issuer")
        except KeyError:
            raise MissingRequiredAttribute("iss")

    if _jwe is not None:
        # Use the original encrypted token to set correct headers
        idt = IdToken().from_jwt(str(instance["id_token"]), **args)
    else:
        idt = IdToken().from_jwt(_jws, **args)
    if not idt.verify(**kwargs):
        raise VerificationError("Could not verify id_token", idt)

    if check_hash:
        _alg = idt.jws_header["alg"]
        # What if _alg == 'none'

        hfunc = "HS" + _alg[-3:]

        if "access_token" in instance:
            if "at_hash" not in idt:
                raise MissingRequiredAttribute("Missing at_hash property", idt)
            if idt["at_hash"] != jws.left_hash(instance["access_token"],
                                               hfunc):
                raise AtHashError("Failed to verify access_token hash", idt)

        if "code" in instance:
            if "c_hash" not in idt:
                raise MissingRequiredAttribute("Missing c_hash property", idt)
            if idt["c_hash"] != jws.left_hash(instance["code"], hfunc):
                raise CHashError("Failed to verify code hash", idt)

    return idt
Example #3
0
def verify_id_token(instance, check_hash=False, **kwargs):
    # Try to decode the JWT, checks the signature
    args = {}
    for arg in ["key", "keyjar", "algs", "sender"]:
        try:
            args[arg] = kwargs[arg]
        except KeyError:
            pass

    _jws = str(instance["id_token"])

    # It can be encrypted, so try to decrypt first
    _jwe = JWE_factory(_jws)
    if _jwe is not None:
        try:
            _jws = _jwe.decrypt(keys=kwargs['keyjar'].get_decrypt_key())
        except JWEException as err:
            raise VerificationError("Could not decrypt id_token", err)
    _packer = JWT()
    _body = _packer.unpack(_jws).payload()

    if 'keyjar' in kwargs:
        try:
            if _body['iss'] not in kwargs['keyjar']:
                raise ValueError('Unknown issuer')
        except KeyError:
            raise MissingRequiredAttribute('iss')

    if _jwe is not None:
        # Use the original encrypted token to set correct headers
        idt = IdToken().from_jwt(str(instance['id_token']), **args)
    else:
        idt = IdToken().from_jwt(_jws, **args)
    if not idt.verify(**kwargs):
        raise VerificationError("Could not verify id_token", idt)

    if check_hash:
        _alg = idt.jws_header["alg"]
        # What if _alg == 'none'

        hfunc = "HS" + _alg[-3:]

        if "access_token" in instance:
            if "at_hash" not in idt:
                raise MissingRequiredAttribute("Missing at_hash property", idt)
            if idt["at_hash"] != jws.left_hash(instance["access_token"], hfunc):
                raise AtHashError("Failed to verify access_token hash", idt)

        if "code" in instance:
            if "c_hash" not in idt:
                raise MissingRequiredAttribute("Missing c_hash property", idt)
            if idt["c_hash"] != jws.left_hash(instance["code"], hfunc):
                raise CHashError("Failed to verify code hash", idt)

    return idt
Example #4
0
    def _create_signed_id_token(
        self,
        client_id,  # type: str
        sub,  # type: str
        user_claims=None,  # type: Optional[Mapping[str, Union[str, List[str]]]]
        nonce=None,  # type: Optional[str]
        authorization_code=None,  # type: Optional[str]
        access_token_value=None,  # type: Optional[str]
        extra_id_token_claims=None
    ):  # type: Optional[Mappings[str, Union[str, List[str]]]]
        # type: (...) -> str
        """
        Creates a signed ID Token.
        :param client_id: who the ID Token is intended for
        :param sub: who the ID Token is regarding
        :param user_claims: any claims about the user to be included
        :param nonce: nonce from the authentication request
        :param authorization_code: the authorization code issued together with this ID Token
        :param access_token_value: the access token issued together with this ID Token
        :param extra_id_token_claims: any extra claims that should be included in the ID Token
        :return: a JWS, containing the ID Token as payload
        """

        alg = self.clients[client_id].get(
            'id_token_signed_response_alg', self.configuration_information[
                'id_token_signing_alg_values_supported'][0])
        args = {}

        hash_alg = 'HS{}'.format(alg[-3:])
        if authorization_code:
            args['c_hash'] = jws.left_hash(authorization_code.encode('utf-8'),
                                           hash_alg)
        if access_token_value:
            args['at_hash'] = jws.left_hash(access_token_value.encode('utf-8'),
                                            hash_alg)

        if user_claims:
            args.update(user_claims)

        if extra_id_token_claims:
            args.update(extra_id_token_claims)

        id_token = IdToken(iss=self.configuration_information['issuer'],
                           sub=sub,
                           aud=client_id,
                           iat=int(time.time()),
                           exp=int(time.time()) + self.id_token_lifetime,
                           **args)

        if nonce:
            id_token['nonce'] = nonce

        logger.debug('signed id_token with kid=%s using alg=%s',
                     self.signing_key, alg)
        return id_token.to_jwt([self.signing_key], alg)
Example #5
0
    def validate_access_token(alg, expected_hash, access_token):
        if alg == None:
            raise OAuth2ProtocolError("No hash algorithm specified")
        if alg.lower() == 'rs256':
            hash = jws.left_hash(access_token)
        else:
            hash = jws.left_hash(access_token, alg)            

        if hash == None:
            raise OAuth2Exception("Hash failed, alg = '" + alg + "', token is '" + access_token + "'")
        if hash != expected_hash:
            raise OAuth2Exception("Bad hash value in access token")
    def verify(self, **kwargs):
        super(AuthorizationResponse, self).verify(**kwargs)

        if "aud" in self:
            if "client_id" in kwargs:
                # check that it's for me
                if kwargs["client_id"] not in self["aud"]:
                    return False

        if "id_token" in self:
            # Try to decode the JWT, checks the signature
            args = {}
            for arg in ["key", "keyjar", "algs", "sender"]:
                try:
                    args[arg] = kwargs[arg]
                except KeyError:
                    pass
            idt = IdToken().from_jwt(str(self["id_token"]), **args)
            if not idt.verify(**kwargs):
                raise VerificationError("Could not verify id_token", idt)

            _alg = idt.jws_header["alg"]
            # What if _alg == 'none'

            hfunc = "HS" + _alg[-3:]

            if "access_token" in self:
                try:
                    assert "at_hash" in idt
                except AssertionError:
                    raise MissingRequiredAttribute("Missing at_hash property",
                                                   idt)
                try:
                    assert idt["at_hash"] == jws.left_hash(
                        self["access_token"], hfunc)
                except AssertionError:
                    raise AtHashError(
                        "Failed to verify access_token hash", idt)

            if "code" in self:
                try:
                    assert "c_hash" in idt
                except AssertionError:
                    raise MissingRequiredAttribute("Missing c_hash property",
                                                   idt)
                try:
                    assert idt["c_hash"] == jws.left_hash(self["code"], hfunc)
                except AssertionError:
                    raise CHashError("Failed to verify code hash", idt)

            self["id_token"] = idt
        return True
Example #7
0
    def verify(self, **kwargs):
        super(AuthorizationResponse, self).verify(**kwargs)

        if "aud" in self:
            if "client_id" in kwargs:
                # check that it's for me
                if kwargs["client_id"] not in self["aud"]:
                    return False

        if "id_token" in self:
            # Try to decode the JWT, checks the signature
            args = {}
            for arg in ["key", "keyjar", "algs", "sender"]:
                try:
                    args[arg] = kwargs[arg]
                except KeyError:
                    pass
            idt = IdToken().from_jwt(str(self["id_token"]), **args)
            if not idt.verify(**kwargs):
                raise VerificationError("Could not verify id_token", idt)

            _alg = idt.jws_header["alg"]
            # What if _alg == 'none'

            hfunc = "HS" + _alg[-3:]

            if "access_token" in self:
                try:
                    assert "at_hash" in idt
                except AssertionError:
                    raise MissingRequiredAttribute("Missing at_hash property",
                                                   idt)
                try:
                    assert idt["at_hash"] == jws.left_hash(
                        self["access_token"], hfunc)
                except AssertionError:
                    raise AtHashError("Failed to verify access_token hash",
                                      idt)

            if "code" in self:
                try:
                    assert "c_hash" in idt
                except AssertionError:
                    raise MissingRequiredAttribute("Missing c_hash property",
                                                   idt)
                try:
                    assert idt["c_hash"] == jws.left_hash(self["code"], hfunc)
                except AssertionError:
                    raise CHashError("Failed to verify code hash", idt)

            self["id_token"] = idt
        return True
    def test_make_id_token(self):
        self.srv.keyjar["http://oic.example/rp"] = KC_RSA

        session = {"sub": "user0",
                   "client_id": "http://oic.example/rp"}
        issuer = "http://oic.example/idp"
        code = "abcdefghijklmnop"
        _idt = self.srv.make_id_token(session, loa="2", issuer=issuer,
                                      code=code, access_token="access_token")

        algo = "RS256"
        ckey = self.srv.keyjar.get_signing_key(alg2keytype(algo),
                                               session["client_id"])
        _signed_jwt = _idt.to_jwt(key=ckey, algorithm="RS256")

        idt = IdToken().from_jwt(_signed_jwt, keyjar=self.srv.keyjar)
        _jwt = JWT().unpack(_signed_jwt)

        lha = left_hash(code.encode("utf-8"),
                        func="HS" + _jwt.headers["alg"][-3:])
        assert lha == idt["c_hash"]

        atr = AccessTokenResponse(id_token=_signed_jwt,
                                  access_token="access_token",
                                  token_type="Bearer")
        atr["code"] = code
        assert atr.verify(keyjar=self.srv.keyjar)
Example #9
0
def test_make_id_token():
    srv = Server()
    srv.keyjar = KEYJ
    srv.keyjar["http://oic.example/rp"] = KC_RSA

    session = {"sub": "user0", "client_id": "http://oic.example/rp"}
    issuer = "http://oic.example/idp"
    code = "abcdefghijklmnop"
    _idt = srv.make_id_token(session,
                             loa="2",
                             issuer=issuer,
                             code=code,
                             access_token="access_token")

    algo = "RS256"
    ckey = srv.keyjar.get_signing_key(alg2keytype(algo), session["client_id"])
    _signed_jwt = _idt.to_jwt(key=ckey, algorithm="RS256")

    idt = IdToken().from_jwt(_signed_jwt, keyjar=srv.keyjar)
    print idt
    header = unpack(_signed_jwt)

    lha = left_hash(code, func="HS" + header[0]["alg"][-3:])
    assert lha == idt["c_hash"]

    atr = AccessTokenResponse(id_token=_signed_jwt,
                              access_token="access_token",
                              token_type="Bearer")
    atr["code"] = code
    assert atr.verify(keyjar=srv.keyjar)
Example #10
0
def test_verify_id_token_at_hash_fail():
    token = 'AccessTokenWhichCouldBeASignedJWT'
    token2 = 'ACompletelyOtherAccessToken'
    lhsh = left_hash(token)

    idt = IdToken(**{
        "sub": "553df2bcf909104751cfd8b2",
        "aud": [
            "5542958437706128204e0000",
            "554295ce3770612820620000"
            ],
        "auth_time": 1441364872,
        "azp": "554295ce3770612820620000",
        "at_hash": lhsh
        })

    kj = KeyJar()
    kj.add_symmetric("", 'dYMmrcQksKaPkhdgRNYk3zzh5l7ewdDJ', ['sig'])
    kj.add_symmetric("https://sso.qa.7pass.ctf.prosiebensat1.com",
                     'dYMmrcQksKaPkhdgRNYk3zzh5l7ewdDJ', ['sig'])
    packer = JWT(kj, sign_alg='HS256',
                 iss="https://sso.qa.7pass.ctf.prosiebensat1.com",
                 lifetime=3600)
    _jws = packer.pack(**idt.to_dict())
    msg = AuthorizationResponse(access_token=token2, id_token=_jws)
    with pytest.raises(AtHashError):
        verify_id_token(msg, check_hash=True, keyjar=kj,
                        iss="https://sso.qa.7pass.ctf.prosiebensat1.com",
                        client_id="554295ce3770612820620000")
Example #11
0
def test_verify_id_token_at_hash():
    token = "AccessTokenWhichCouldBeASignedJWT"
    lhsh = left_hash(token)

    idt = IdToken(
        **{
            "sub": "553df2bcf909104751cfd8b2",
            "aud": ["5542958437706128204e0000", "554295ce3770612820620000"],
            "auth_time": 1441364872,
            "azp": "554295ce3770612820620000",
            "at_hash": lhsh,
        })

    kj = KeyJar()
    kj.add_symmetric("", "dYMmrcQksKaPkhdgRNYk3zzh5l7ewdDJ", ["sig"])
    kj.add_symmetric(
        "https://sso.qa.7pass.ctf.prosiebensat1.com",
        "dYMmrcQksKaPkhdgRNYk3zzh5l7ewdDJ",
        ["sig"],
    )
    packer = JWT(
        kj,
        sign_alg="HS256",
        iss="https://sso.qa.7pass.ctf.prosiebensat1.com",
        lifetime=3600,
    )
    _jws = packer.pack(**idt.to_dict())
    msg = AuthorizationResponse(access_token=token, id_token=_jws)
    verify_id_token(
        msg,
        check_hash=True,
        keyjar=kj,
        iss="https://sso.qa.7pass.ctf.prosiebensat1.com",
        client_id="554295ce3770612820620000",
    )
    def test_handle_implicit_authentication_response(self, time_mock,
                                                     utc_time_sans_frac_mock):
        # freeze time since ID Token validation includes expiration timestamps
        timestamp = time.mktime(datetime(2017, 1, 1).timetuple())
        time_mock.return_value = timestamp
        utc_time_sans_frac_mock.return_value = int(timestamp)

        # mock auth response
        access_token = 'test_access_token'
        user_id = 'user1'
        exp_time = 10
        nonce = 'test_nonce'
        id_token_claims = {
            'iss': self.PROVIDER_BASEURL,
            'aud': [self.CLIENT_ID],
            'sub': user_id,
            'exp': int(timestamp) + exp_time,
            'iat': int(timestamp),
            'nonce': nonce,
            'at_hash': jws.left_hash(access_token)
        }
        id_token_jwt, id_token_signing_key = signed_id_token(id_token_claims)

        responses.add(responses.GET,
                      self.PROVIDER_BASEURL + '/jwks',
                      json={'keys': [id_token_signing_key.serialize()]})

        # mock userinfo response
        userinfo = {'sub': user_id, 'name': 'Test User'}
        userinfo_endpoint = self.PROVIDER_BASEURL + '/userinfo'
        responses.add(responses.GET, userinfo_endpoint, json=userinfo)

        authn = self.init_app(
            provider_metadata_extras={'userinfo_endpoint': userinfo_endpoint})
        state = 'test_state'
        auth_response = AuthorizationResponse(
            **{
                'state': state,
                'access_token': access_token,
                'token_type': 'Bearer',
                'id_token': id_token_jwt
            })
        with self.app.test_request_context('/redirect_uri?{}'.format(
                auth_response.to_urlencoded())):
            UserSession(flask.session, self.PROVIDER_NAME)
            flask.session['destination'] = '/'
            flask.session['auth_request'] = json.dumps({
                'state': state,
                'nonce': nonce
            })
            authn._handle_authentication_response()
            session = UserSession(flask.session)
            assert session.access_token == access_token
            assert session.id_token == id_token_claims
            assert session.id_token_jwt == id_token_jwt
            assert session.userinfo == userinfo
Example #13
0
    def val_hash(self, alg):
        halg = "HS%s" % alg[-3:]

        for attr, hash_attr in self.hashable.items():
            try:
                self[hash_attr] = jws.left_hash(as_unicode(self[attr]), halg)
            except KeyError:
                pass
            else:
                del self[attr]
Example #14
0
def test_verify_id_token_c_hash_fail():
    code = "AccessCode1"
    lhsh = left_hash(code)

    idt = IdToken(
        **{
            "sub": "553df2bcf909104751cfd8b2",
            "aud": ["5542958437706128204e0000", "554295ce3770612820620000"],
            "auth_time": 1441364872,
            "azp": "554295ce3770612820620000",
            "c_hash": lhsh,
        }
    )

    kj = KeyJar()
    kj.add_symmetric("", "dYMmrcQksKaPkhdgRNYk3zzh5l7ewdDJ", ["sig"])
    kj.add_symmetric(
        "https://sso.qa.7pass.ctf.prosiebensat1.com",
        "dYMmrcQksKaPkhdgRNYk3zzh5l7ewdDJ",
        ["sig"],
    )
    packer = JWT(
        kj,
        sign_alg="HS256",
        iss="https://sso.qa.7pass.ctf.prosiebensat1.com",
        lifetime=3600,
    )
    _jws = packer.pack(**idt.to_dict())
    msg = AuthorizationResponse(code="AccessCode289", id_token=_jws)
    with pytest.raises(CHashError):
        verify_id_token(
            msg,
            check_hash=True,
            keyjar=kj,
            iss="https://sso.qa.7pass.ctf.prosiebensat1.com",
            client_id="554295ce3770612820620000",
        )
Example #15
0
    def make_id_token(
        self,
        session,
        loa="2",
        issuer="",
        alg="RS256",
        code=None,
        access_token=None,
        user_info=None,
        auth_time=0,
        exp=None,
        extra_claims=None,
    ):
        """

        :param session: Session information
        :param loa: Level of Assurance/Authentication context
        :param issuer: My identifier
        :param alg: Which signing algorithm to use for the IdToken
        :param code: Access grant
        :param access_token: Access Token
        :param user_info: If user info are to be part of the IdToken
        :return: IDToken instance
        """
        # defaults
        if exp is None:
            inawhile = {"days": 1}
        else:
            inawhile = exp
        # Handle the idtoken_claims
        extra = {}
        itc = self.id_token_claims(session)
        if itc:
            try:
                inawhile = {"seconds": itc["max_age"]}
            except KeyError:
                pass
            for key, val in itc.items():
                if key == "auth_time":
                    extra["auth_time"] = auth_time
                elif key == "acr":
                    # ["2","http://id.incommon.org/assurance/bronze"]
                    extra["acr"] = verify_acr_level(val, loa)
        else:
            if auth_time:
                extra["auth_time"] = auth_time
            if loa:
                extra["acr"] = loa

        if not user_info:
            _args = {}
        else:
            try:
                _args = user_info.to_dict()
            except AttributeError:
                _args = user_info

        # Make sure that there are no name clashes
        for key in ["iss", "sub", "aud", "exp", "acr", "nonce", "auth_time"]:
            try:
                del _args[key]
            except KeyError:
                pass

        halg = "HS%s" % alg[-3:]

        if extra_claims is not None:
            _args.update(extra_claims)
        if code:
            _args["c_hash"] = jws.left_hash(code.encode("utf-8"), halg)
        if access_token:
            _args["at_hash"] = jws.left_hash(access_token.encode("utf-8"), halg)

        # Should better be done elsewhere
        if not issuer.endswith("/"):
            issuer += "/"

        idt = IdToken(
            iss=issuer,
            sub=session["sub"],
            aud=session["client_id"],
            exp=time_util.epoch_in_a_while(**inawhile),
            acr=loa,
            iat=time_util.utc_time_sans_frac(),
            **_args
        )

        for key, val in extra.items():
            idt[key] = val

        if "nonce" in session:
            idt["nonce"] = session["nonce"]

        return idt
Example #16
0
def test_left_hash_hs512():
    hsh = jws.left_hash("Please take a moment to register today", "HS512")
    assert hsh == "_h6feWLt8zbYcOFnaBmekTzMJYEHdVTaXlDgJSWsEeY"
Example #17
0
def test_left_hash_hs256():
    hsh = jws.left_hash("Please take a moment to register today")
    assert hsh == "rCFHVJuxTqRxOsn2IUzgvA"
Example #18
0
    def make_id_token(self,
                      session,
                      loa="2",
                      issuer="",
                      alg="RS256",
                      code=None,
                      access_token=None,
                      user_info=None,
                      auth_time=0):
        """

        :param session: Session information
        :param loa: Level of Assurance/Authentication context
        :param issuer: My identifier
        :param alg: Which signing algorithm to use for the IdToken
        :param code: Access grant
        :param access_token: Access Token
        :param user_info: If user info are to be part of the IdToken
        :return: IDToken instance
        """
        #defaults
        inawhile = {"days": 1}
        # Handle the idtoken_claims
        extra = {}
        itc = self.id_token_claims(session)
        if itc:
            try:
                inawhile = {"seconds": itc["max_age"]}
            except KeyError:
                inawhile = {}
            for key, val in itc.items():
                if key == "auth_time":
                    extra["auth_time"] = auth_time
                elif key == "acr":
                    #["2","http://id.incommon.org/assurance/bronze"]
                    extra["acr"] = verify_acr_level(val, loa)

        if user_info is None:
            _args = {}
        else:
            try:
                _args = user_info.to_dict()
            except AttributeError:
                _args = user_info

        # Make sure that there are no name clashes
        for key in ["iss", "sub", "aud", "exp", "acr", "nonce", "auth_time"]:
            try:
                del _args[key]
            except KeyError:
                pass

        halg = "HS%s" % alg[-3:]

        if code:
            _args["c_hash"] = jws.left_hash(code, halg)
        if access_token:
            _args["at_hash"] = jws.left_hash(access_token, halg)

        idt = IdToken(iss=issuer,
                      sub=session["sub"],
                      aud=session["client_id"],
                      exp=time_util.epoch_in_a_while(**inawhile),
                      acr=loa,
                      iat=time_util.utc_now(),
                      **_args)

        for key, val in extra.items():
            idt[key] = val

        if "nonce" in session:
            idt["nonce"] = session["nonce"]

        return idt
Example #19
0
def test_left_hash_hs512():
    hsh = jws.left_hash('Please take a moment to register today', "HS512")
    assert hsh == '_h6feWLt8zbYcOFnaBmekTzMJYEHdVTaXlDgJSWsEeY'
Example #20
0
    def make_id_token(self, session, loa="2", issuer="",
                      alg="RS256", code=None, access_token=None,
                      user_info=None):
        """

        :param session: Session information
        :param loa: Level of Assurance/Authentication context
        :param issuer: My identifier
        :param alg: Which signing algorithm to use for the IdToken
        :param code: Access grant
        :param access_token: Access Token
        :param user_info: If user info are to be part of the IdToken
        :return: IDToken instance
        """
        #defaults
        inawhile = {"days": 1}
        # Handle the idtoken_claims
        extra = {}
        itc = self.id_token_claims(session)
        if itc:
            try:
                inawhile = {"seconds": itc["max_age"]}
            except KeyError:
                inawhile = {}
            if "claims" in itc:
                for key, val in itc["claims"].items():
                    if key == "auth_time":
                        extra["auth_time"] = time_util.utc_time_sans_frac()
                    elif key == "acr":
                        #["2","http://id.incommon.org/assurance/bronze"]
                        extra["acr"] = verify_acr_level(val, loa)

        if user_info is None:
            _args = {}
        else:
            _args = user_info.to_dict()

        # Make sure that there are no name clashes
        for key in ["iss", "sub", "aud", "exp", "acr", "nonce",
                    "auth_time"]:
            try:
                del _args[key]
            except KeyError:
                pass

        halg = "HS%s" % alg[-3:]

        if code:
            _args["c_hash"] = jws.left_hash(code, halg)
        if access_token:
            _args["at_hash"] = jws.left_hash(access_token, halg)

        idt = IdToken(iss=issuer, sub=session["sub"],
                      aud = session["client_id"],
                      exp = time_util.epoch_in_a_while(**inawhile), acr=loa,
                      iat = time_util.utc_now(),
                      **_args)

        for key, val in extra.items():
            idt[key] = val

        if "nonce" in session:
            idt.nonce = session["nonce"]

        return idt
    def __call__(self, request):
        data = request.body

        req = self.provider.parse_token_request(body=data)

        if 'grant_type' not in req:
            return (400, {}, 'Missing grant_type')

        if req['grant_type'] == 'authorization_code':
            authz_code = req['code']
            authz_info = self.provider.authz_codes[authz_code]
            auth_req = authz_info['auth_req']
            client_id = auth_req['client_id']

            if authz_info['used']:
                raise Exception('code already used')
                return (400, {}, 'Invalid authorization code')

            if authz_info['exp'] < time.time():
                raise Exception('code expired')
                return (400, {}, 'Invalid authorization code')

            authz_info['used'] = True

            access_token = {
                'value': rndstr(),
                'expires_in': self.provider.access_token_lifetime,
                'type': 'Bearer'
            }

            at_value = access_token['value']

            self.provider.access_tokens[at_value] = {
                'iat': time.time(),
                'exp': time.time() + self.provider.access_token_lifetime,
                'sub': 'test-sub',
                'client_id': client_id,
                'aud': [client_id],
                'scope': authz_info['granted_scope'],
                'granted_scope': authz_info['granted_scope'],
                'token_type': access_token['type'],
                'auth_req': auth_req
            }

            resp = AccessTokenResponse()
            resp['access_token'] = at_value
            resp['token_type'] = access_token['type']
            resp['expires_in'] = access_token['expires_in']

            resp['refresh_token'] = None

            args = {
                'c_hash': jws.left_hash(authz_code.encode('utf-8'), 'HS256'),
                'at_hash': jws.left_hash(at_value.encode('utf-8'), 'HS256'),
            }

            id_token = IdToken(iss=self.config['issuer'],
                               sub='test-sub',
                               aud=client_id,
                               iat=time.time(),
                               exp=time.time() +
                               self.provider.id_token_lifetime,
                               **args)

            if 'nonce' in auth_req:
                id_token['nonce'] = auth_req['nonce']

            resp['id_token'] = id_token.to_jwt([self.provider.signing_key],
                                               'RS256')

            json_data = resp.to_json()

            return (200, {
                'Content-Type': 'application/json',
                'Cache-Control': 'no-store',
                'Pragma': 'no-cache',
            }, json_data)

        return (400, {}, 'Unsupported grant_type')
Example #22
0
def test_left_hash_hs256():
    hsh = jws.left_hash('Please take a moment to register today')
    assert hsh == 'rCFHVJuxTqRxOsn2IUzgvA'
    def __call__(self, request):
        data = request.body

        req = self.provider.parse_token_request(body=data)

        if 'grant_type' not in req:
            return (400, {}, 'Missing grant_type')

        if req['grant_type'] == 'authorization_code':
            authz_code = req['code']
            authz_info = self.provider.authz_codes[authz_code]
            auth_req = authz_info['auth_req']
            client_id = auth_req['client_id']

            if authz_info['used']:
                raise Exception('code already used')
                return (400, {}, 'Invalid authorization code')

            if authz_info['exp'] < time.time():
                raise Exception('code expired')
                return (400, {}, 'Invalid authorization code')

            authz_info['used'] = True

            access_token = {
                'value': rndstr(),
                'expires_in': self.provider.access_token_lifetime,
                'type': 'Bearer'
            }

            at_value = access_token['value']

            self.provider.access_tokens[at_value] = {
                'iat': time.time(),
                'exp': time.time() + self.provider.access_token_lifetime,
                'sub': 'test-sub',
                'client_id': client_id,
                'aud': [client_id],
                'scope': authz_info['granted_scope'],
                'granted_scope': authz_info['granted_scope'],
                'token_type': access_token['type'],
                'auth_req': auth_req
            }

            resp = AccessTokenResponse()
            resp['access_token'] = at_value
            resp['token_type'] = access_token['type']
            resp['expires_in'] = access_token['expires_in']

            resp['refresh_token'] = None

            args = {
                'c_hash': jws.left_hash(authz_code.encode('utf-8'), 'HS256'),
                'at_hash': jws.left_hash(at_value.encode('utf-8'), 'HS256'),
            }

            id_token = IdToken(
                iss=self.config['issuer'],
                sub='test-sub',
                aud=client_id,
                iat=time.time(),
                exp=time.time() + self.provider.id_token_lifetime,
                **args)

            if 'nonce' in auth_req:
                id_token['nonce'] = auth_req['nonce']

            resp['id_token'] = id_token.to_jwt(
                [self.provider.signing_key], 'RS256')

            json_data = resp.to_json()

            return (
                200,
                {
                    'Content-Type': 'application/json',
                    'Cache-Control': 'no-store',
                    'Pragma': 'no-cache',
                },
                json_data
            )

        return (400, {}, 'Unsupported grant_type')