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)
Esempio n. 2
0
    def test_token_endpoint(self):
        authreq = AuthorizationRequest(state="state",
                                       redirect_uri="http://example.com/authz",
                                       client_id=CLIENT_ID,
                                       response_type="code",
                                       scope=["openid"])

        _sdb = self.provider.sdb
        sid = _sdb.token.key(user="******", areq=authreq)
        access_grant = _sdb.token(sid=sid)
        ae = AuthnEvent("user", "salt")
        _sdb[sid] = {
            "oauth_state": "authz",
            "authn_event": ae,
            "authzreq": authreq.to_json(),
            "client_id": CLIENT_ID,
            "code": access_grant,
            "code_used": False,
            "scope": ["openid"],
            "redirect_uri": "http://example.com/authz",
        }
        _sdb.do_sub(sid, "client_salt")

        # Construct Access token request
        areq = AccessTokenRequest(code=access_grant, client_id=CLIENT_ID,
                                  redirect_uri="http://example.com/authz",
                                  client_secret=CLIENT_SECRET)

        txt = areq.to_urlencoded()

        resp = self.provider.token_endpoint(request=txt)
        atr = AccessTokenResponse().deserialize(resp.message, "json")
        assert _eq(atr.keys(),
                   ['token_type', 'id_token', 'access_token', 'scope',
                    'expires_in', 'refresh_token'])
Esempio n. 3
0
def test_token_endpoint():
    server = provider_init

    authreq = AuthorizationRequest(state="state",
                                   redirect_uri="http://example.com/authz",
                                   client_id=CLIENT_ID)

    _sdb = server.sdb
    sid = _sdb.token.key(user="******", areq=authreq)
    access_grant = _sdb.token(sid=sid)
    _sdb[sid] = {
        "oauth_state": "authz",
        "sub": "user_id",
        "authzreq": "",
        "client_id": CLIENT_ID,
        "code": access_grant,
        "code_used": False,
        "scope": ["openid"],
        "redirect_uri": "http://example.com/authz"
    }

    # Construct Access token request
    areq = AccessTokenRequest(code=access_grant, client_id=CLIENT_ID,
                              redirect_uri="http://example.com/authz",
                              client_secret=CLIENT_SECRET)

    txt = areq.to_urlencoded()

    resp = server.token_endpoint(request=txt)
    print resp
    atr = AccessTokenResponse().deserialize(resp.message, "json")
    print atr.keys()
    assert _eq(atr.keys(), ['token_type', 'id_token', 'access_token', 'scope',
                            'expires_in', 'refresh_token'])
Esempio n. 4
0
 def make_refresh_request(self, refresh_token):
     request_args = {
         'grant_type': 'refresh_token',
         'refresh_token': refresh_token,
     }
     resp = self.app.test_client().post('/token', data=request_args, headers=self.create_basic_auth_header())
     assert resp.status_code == 200
     token_response = AccessTokenResponse().from_json(resp.data.decode('utf-8'))
     assert token_response.verify()
     return token_response
Esempio n. 5
0
 def make_code_exchange_request(self, code):
     request_args = {
         'grant_type': 'authorization_code',
         'code': code,
         'redirect_uri': TEST_REDIRECT_URI
     }
     resp = self.app.test_client().post('/token', data=request_args, headers=self.create_basic_auth_header())
     assert resp.status_code == 200
     token_response = AccessTokenResponse().from_json(resp.data.decode('utf-8'))
     assert token_response.verify(key=[self.app.provider.signing_key])
     return token_response
Esempio n. 6
0
def test_clean_response():
    atr = AccessTokenResponse(access_token="access_token",
                              token_type="bearer", expires_in=600,
                              refresh_token="refresh", steps=39, stalls="yes")

    catr = clean_response(atr)
    atr_keys = atr.keys()
    catr_keys = catr.keys()
    assert _eq(atr_keys, ['token_type', 'access_token', 'expires_in',
                          'refresh_token', 'steps', 'stalls'])
    assert _eq(catr_keys, ['token_type', 'access_token', 'expires_in',
                           'refresh_token'])
Esempio n. 7
0
    def test_wrong_alg(self):
        idval = {'nonce': 'KUEYfRM2VzKDaaKD', 'sub': 'EndUserSubject',
                 'iss': 'https://alpha.cloud.nds.rub.de', 'exp': 1420823073,
                 'iat': 1420822473, 'aud': 'TestClient'}
        idts = IdToken(**idval)
        key = SYMKey(key="TestPassword")
        _signed_jwt = idts.to_jwt(key=[key], algorithm="HS256")

        _info = {"access_token": "accessTok", "id_token": _signed_jwt,
                 "token_type": "Bearer", "expires_in": 3600}

        at = AccessTokenResponse(**_info)
        with pytest.raises(WrongSigningAlgorithm):
            at.verify(key=[key], algs={"sign": "HS512"})
Esempio n. 8
0
def clean_response(aresp):
    """
    Creates a new instance with only the standard attributes

    :param aresp: The original AccessTokenResponse
    :return: An AccessTokenResponse instance
    """
    atr = AccessTokenResponse()
    for prop in atr.parameters():
        try:
            atr[prop] = aresp[prop]
        except KeyError:
            pass

    return atr
Esempio n. 9
0
def test_parse_access_token_response_missing_attribute():
    at = AccessTokenResponse(access_token="SlAV32hkKG", token_type="Bearer",
                             refresh_token="8xLOxBtZp8", expires_in=3600)

    atdict = at.to_dict()
    del atdict["access_token"]
    atj = json.dumps(atdict)
    print atj
    client = Client()
    ATR = AccessTokenResponse

    raises(MissingRequiredAttribute, "client.parse_response(ATR, info=atj)")

    atuec = urllib.urlencode(atdict)

    raises(MissingRequiredAttribute,
           "client.parse_response(ATR, info=atuec, sformat='urlencoded')")
Esempio n. 10
0
    def token_endpoint(self, data):
        if "grant_type=refresh_token" in data:
            req = self.parse_refresh_token_request(body=data)
            _info = self.sdb.refresh_token(req["refresh_token"])
        elif "grant_type=authorization_code":
            req = self.parse_token_request(body=data)
            _info = self.sdb.upgrade_to_token(req["code"])
        else:
            response = TokenErrorResponse(error="unsupported_grant_type")
            return response, ""

        resp = AccessTokenResponse(**by_schema(AccessTokenResponse, **_info))
        response = Response()
        response.headers = {"content-type": "application/json"}
        response.text = resp.to_json()

        return response
Esempio n. 11
0
def test_make_id_token():
    srv = Server(KEYS)
    session = {"user_id": "user0", "client_id": "http://oic.example/rp"}
    issuer = "http://oic.example/idp"
    code = "abcdefghijklmnop"
    idt_jwt = srv.make_id_token(session, loa="2", issuer=issuer, code=code, access_token="access_token")

    jwt_keys = srv.keystore.get_keys("ver", owner=None)
    idt = IdToken().from_jwt(idt_jwt, key=jwt_keys)
    print idt
    header = unpack(idt_jwt)

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

    atr = AccessTokenResponse(id_token=idt_jwt, access_token="access_token", token_type="Bearer")
    atr["code"] = code
    assert atr.verify(key=jwt_keys)
    def test_userinfo_request(self):
        aresp = AuthorizationResponse(code="code", state="state000")
        tresp = AccessTokenResponse(access_token="access_token",
                                    token_type="Bearer",
                                    expires_in=600, refresh_token="refresh",
                                    scope=["openid"])

        self.client.parse_response(AuthorizationResponse, aresp.to_urlencoded(),
                                   sformat="urlencoded", state="state0")
        self.client.parse_response(AccessTokenResponse, tresp.to_json(),
                                   state="state0")

        path, body, method, h_args = self.client.user_info_request(
                state="state0")
        assert path == "http://example.com/userinfo"
        assert method == "GET"
        assert body is None
        assert h_args == {'headers': {'Authorization': 'Bearer access_token'}}
Esempio n. 13
0
def test_parse_access_token_response():
    client = Client()

    at = AccessTokenResponse(access_token="SlAV32hkKG", token_type="Bearer",
                             refresh_token="8xLOxBtZp8", expires_in=3600)

    atj = at.to_json()

    ATR = AccessTokenResponse
    atr = client.parse_response(ATR, info=atj)

    assert _eq(atr.keys(), ['access_token', 'token_type', 'expires_in',
                            'refresh_token'])

    uec = at.to_urlencoded()
    raises(ValueError, 'client.parse_response(ATR, info=uec)')

    uatr = client.parse_response(ATR, info=uec, sformat="urlencoded")
    assert _eq(uatr.keys(), ['access_token', 'token_type', 'expires_in',
                             'refresh_token'])

    huec = "%s?%s" % ("https://example.com/token", uec)

    uatr = client.parse_response(ATR, info=huec, sformat="urlencoded")
    assert _eq(uatr.keys(), ['access_token', 'token_type', 'expires_in',
                             'refresh_token'])

    err = ErrorResponse(error="invalid_request",
                        error_description="Something was missing",
                        error_uri="http://example.com/error_message.html")

    jerr = err.to_json()
    uerr = err.to_urlencoded()

    _ = client.parse_response(ATR, info=jerr)
    _ = client.parse_response(ATR, info=uerr, sformat="urlencoded")

    raises(Exception,
           'client.parse_response(ATR, info=jerr, sformat="urlencoded")')

    raises(Exception, "client.parse_response(ATR, info=uerr)")

    raises(Exception,
           'client.parse_response(ATR, info=jerr, sformat="focus")')
Esempio n. 14
0
    def test_faulty_idtoken(self):
        idval = {'nonce': 'KUEYfRM2VzKDaaKD', 'sub': 'EndUserSubject',
                 'iss': 'https://alpha.cloud.nds.rub.de', 'exp': 1420823073,
                 'iat': 1420822473, 'aud': 'TestClient'}
        idts = IdToken(**idval)
        key = SYMKey(key="TestPassword")
        _signed_jwt = idts.to_jwt(key=[key], algorithm="HS256")

        # Mess with the signed id_token
        p = _signed_jwt.split(".")
        p[2] = "aaa"
        _faulty_signed_jwt = ".".join(p)

        _info = {"access_token": "accessTok", "id_token": _faulty_signed_jwt,
                 "token_type": "Bearer", "expires_in": 3600}

        at = AccessTokenResponse(**_info)
        with pytest.raises(BadSignature):
            at.verify(key=[key])
Esempio n. 15
0
def test_token_endpoint():
    server = provider_init

    authreq = AuthorizationRequest(state="state",
                                   redirect_uri="http://example.com/authz",
                                   client_id=CLIENT_ID)

    _sdb = server.sdb
    sid = _sdb.token.key(user="******", areq=authreq)
    access_grant = _sdb.token(sid=sid)
    _sdb[sid] = {
        "oauth_state": "authz",
        "sub": "user_id",
        "authzreq": "",
        "client_id": CLIENT_ID,
        "code": access_grant,
        "code_used": False,
        "scope": ["openid"],
        "redirect_uri":"http://example.com/authz"
    }

    # Construct Access token request
    areq = AccessTokenRequest(code=access_grant, client_id=CLIENT_ID,
                              redirect_uri="http://example.com/authz",
                              client_secret=CLIENT_SECRET)


    str = areq.to_urlencoded()
    fil = StringIO.StringIO(buf=str)
    environ = BASE_ENVIRON.copy()
    environ["REQUEST_METHOD"] = "POST"
    environ["CONTENT_LENGTH"] = len(str)
    environ["wsgi.input"] = fil
    environ["REMOTE_USER"] = CLIENT_ID

    resp = server.token_endpoint(environ, start_response)
    print resp
    atr = AccessTokenResponse().deserialize(resp[0], "json")
    print atr.keys()
    assert _eq(atr.keys(), ['token_type', 'id_token', 'access_token', 'scope',
                            'expires_in', 'refresh_token'])
    def test_userinfo_request_post(self):
        aresp = AuthorizationResponse(code="code", state="state000")
        tresp = AccessTokenResponse(access_token="access_token",
                                    token_type="bearer",
                                    expires_in=600, refresh_token="refresh",
                                    scope=["openid"])

        self.client.parse_response(AuthorizationResponse, aresp.to_urlencoded(),
                                   sformat="urlencoded", state="state0")
        self.client.parse_response(AccessTokenResponse, tresp.to_json(),
                                   state="state0")

        path, body, method, h_args = self.client.user_info_request(
                method="POST",
                state="state0")

        assert path == "http://example.com/userinfo"
        assert method == "POST"
        assert body == "access_token=access_token"
        assert h_args == {'headers': {
            'Content-Type': 'application/x-www-form-urlencoded'}}
Esempio n. 17
0
    def _refresh_access_token_endpoint(self, req, **kwargs):
        _sdb = self.sdb
        _log_debug = logger.debug

        client_info = self.cdb[req["client_id"]]

        assert req["grant_type"] == "refresh_token"
        rtoken = req["refresh_token"]
        _info = _sdb.refresh_token(rtoken)

        if "openid" in _info["scope"]:
            userinfo = self.userinfo_in_id_token_claims(_info)
            _idtoken = self.sign_encrypt_id_token(_info, client_info, req,
                                                  user_info=userinfo)
            sid = _sdb.token.get_key(rtoken)
            _sdb.update(sid, "id_token", _idtoken)

        _log_debug("_info: %s" % _info)

        atr = AccessTokenResponse(**by_schema(AccessTokenResponse, **_info))

        _log_debug("access_token_response: %s" % atr.to_dict())

        return Response(atr.to_json(), content="application/json")
Esempio n. 18
0
    def _do_token_refresh(self, request):
        # type: (Mapping[str, str]) -> oic.oic.message.AccessTokenResponse
        """
        Handles a token request for refreshing an access token (grant_type=refresh_token).
        :param request: parsed http request parameters
        :return: a token response containing a new Access Token and possibly a new Refresh Token
        :raise InvalidTokenRequest: if the token request is invalid
        """
        token_request = RefreshAccessTokenRequest().from_dict(request)
        try:
            token_request.verify()
        except MessageException as e:
            raise InvalidTokenRequest(str(e), token_request) from e

        response = AccessTokenResponse()

        access_token, refresh_token = self.authz_state.use_refresh_token(
            token_request['refresh_token'], scope=token_request.get('scope'))
        self._add_access_token_to_response(response, access_token)
        if refresh_token:
            response['refresh_token'] = refresh_token

        return response
Esempio n. 19
0
    def test_token_endpoint(self, context, frontend_config, authn_req):
        token_lifetime = 60 * 60 * 24
        frontend_config["provider"]["access_token_lifetime"] = token_lifetime
        frontend = self.frontend(frontend_config)

        user_id = "test_user"
        self.insert_client_in_client_db(frontend, authn_req["redirect_uri"])
        self.insert_user_in_user_db(frontend, user_id)
        authn_req["response_type"] = "code"
        authn_resp = frontend.provider.authorize(authn_req, user_id)

        context.request = AccessTokenRequest(
            redirect_uri=authn_req["redirect_uri"],
            code=authn_resp["code"]).to_dict()
        credentials = "{}:{}".format(CLIENT_ID, CLIENT_SECRET)
        basic_auth = urlsafe_b64encode(
            credentials.encode("utf-8")).decode("utf-8")
        context.request_authorization = "Basic {}".format(basic_auth)

        response = frontend.token_endpoint(context)
        parsed = AccessTokenResponse().deserialize(response.message, "json")
        assert parsed["access_token"]
        assert parsed["expires_in"] == token_lifetime
        assert parsed["id_token"]
Esempio n. 20
0
def test_do_userinfo_request_with_state():
    """ Mirrors the first lines in do_userinfo_request"""
    client = Client(CLIENT_ID, client_authn_method=CLIENT_AUTHN_METHOD)
    client.grant['foxhound'] = Grant()
    resp = AccessTokenResponse(access_token="access", token_type="Bearer")
    _token = Token(resp)
    client.grant["foxhound"].tokens = [_token]

    method = "GET"
    state = "foxhound"
    scope = "openid"
    request = "openid"
    kwargs = {
        "request": request,
        "userinfo_endpoint": 'http://example.com/userinfo'
    }

    path, body, method, h_args = client.user_info_request(
        method, state, scope, **kwargs)

    assert path == 'http://example.com/userinfo'
    assert h_args == {'headers': {'Authorization': 'Bearer access'}}
    assert method == 'GET'
    assert body is None
    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')
Esempio n. 22
0
    def _do_code_exchange(
        self,
        request,  # type: Dict[str, str]
        extra_id_token_claims=None
        # type: Optional[Union[Mapping[str, Union[str, List[str]]], Callable[[str, str], Mapping[str, Union[str, List[str]]]]]
    ):
        # type: (...) -> oic.message.AccessTokenResponse
        """
        Handles a token request for exchanging an authorization code for an access token
        (grant_type=authorization_code).
        :param request: parsed http request parameters
        :param extra_id_token_claims: any extra parameters to include in the signed ID Token, either as a dict-like
            object or as a callable object accepting the local user identifier and client identifier which returns
            any extra claims which might depend on the user id and/or client id.
        :return: a token response containing a signed ID Token, an Access Token, and a Refresh Token
        :raise InvalidTokenRequest: if the token request is invalid
        """
        token_request = AccessTokenRequest().from_dict(request)
        try:
            token_request.verify()
        except MessageException as e:
            raise InvalidTokenRequest(str(e), token_request) from e

        authentication_request = self.authz_state.get_authorization_request_for_code(
            token_request['code'])

        if token_request['client_id'] != authentication_request['client_id']:
            logger.info(
                'Authorization code \'%s\' belonging to \'%s\' was used by \'%s\'',
                token_request['code'], authentication_request['client_id'],
                token_request['client_id'])
            raise InvalidAuthorizationCode('{} unknown'.format(
                token_request['code']))
        if token_request['redirect_uri'] != authentication_request[
                'redirect_uri']:
            raise InvalidTokenRequest(
                'Invalid redirect_uri: {} != {}'.format(
                    token_request['redirect_uri'],
                    authentication_request['redirect_uri']), token_request)

        sub = self.authz_state.get_subject_identifier_for_code(
            token_request['code'])
        user_id = self.authz_state.get_user_id_for_subject_identifier(sub)

        response = AccessTokenResponse()

        access_token = self.authz_state.exchange_code_for_token(
            token_request['code'])
        self._add_access_token_to_response(response, access_token)
        refresh_token = self.authz_state.create_refresh_token(
            access_token.value)
        if refresh_token is not None:
            response['refresh_token'] = refresh_token

        if extra_id_token_claims is None:
            extra_id_token_claims = {}
        elif callable(extra_id_token_claims):
            extra_id_token_claims = extra_id_token_claims(
                user_id, authentication_request['client_id'])
        requested_claims = self._get_requested_claims_in(
            authentication_request, 'id_token')
        user_claims = self.userinfo.get_claims_for(user_id, requested_claims)
        response['id_token'] = self._create_signed_id_token(
            authentication_request['client_id'], sub, user_claims,
            authentication_request.get('nonce'), None, access_token.value,
            extra_id_token_claims)
        logger.debug(
            'issued id_token=%s from requested_claims=%s userinfo=%s extra_claims=%s',
            response['id_token'], requested_claims, user_claims,
            extra_id_token_claims)

        return response
Esempio n. 23
0
    cli.scope = ["openid", "profile"]
    cli.redirect_uris = ["https://client.example.com/cb"]

    request_args = {"response_type": "code id_token", "state": "af0ifjsldkj"}

    oidr = cli.construct_AuthorizationRequest(request_args=request_args)
    print oidr.keys()
    assert _eq(oidr.keys(), [
        'nonce', 'state', 'redirect_uri', 'response_type', 'client_id', 'scope'
    ])


ARESP = AuthorizationResponse(code="code", state="state000")
TRESP = AccessTokenResponse(access_token="access_token",
                            token_type="bearer",
                            expires_in=600,
                            refresh_token="refresh",
                            scope=["openid"])


def test_userinfo_request():
    cli = Client()
    cli.userinfo_endpoint = "http://example.com/userinfo"

    info = ARESP.to_urlencoded()
    cli.parse_response(AuthorizationResponse,
                       info,
                       sformat="urlencoded",
                       state="state0")

    cli.parse_response(AccessTokenResponse, TRESP.to_json(), state="state0")
Esempio n. 24
0
 def test_token_type(self):
     # lacks required token_type parameter
     _info = {"access_token": "accessTok", "id_token": "blabla"}
     at = AccessTokenResponse(**_info)
     with pytest.raises(MissingRequiredAttribute):
         at.verify()
Esempio n. 25
0
            _tinfo = _sdb.update_to_token(_access_code)
        except Exception, err:
            logger.error("%s" % err)
            # Should revoke the token issued to this access code
            _sdb.revoke_all_tokens(_access_code)
            return self._error(error="access_denied", descr="%s" % err)

        if "openid" in _info["scope"]:
            userinfo = self.userinfo_in_id_token_claims(_info)
            _idtoken = self.sign_encrypt_id_token(_info, client_info, req,
                                                  user_info=userinfo)
            _sdb.update_by_token(_access_code, "id_token", _idtoken)

        _log_debug("_tinfo: %s" % _tinfo)

        atr = AccessTokenResponse(**by_schema(AccessTokenResponse, **_tinfo))

        _log_debug("access_token_response: %s" % atr.to_dict())

        return Response(atr.to_json(), content="application/json")

    def _refresh_access_token_endpoint(self, req, **kwargs):
        _sdb = self.sdb
        _log_debug = logger.debug

        client_info = self.cdb[req["client_id"]]

        assert req["grant_type"] == "refresh_token"
        rtoken = req["refresh_token"]
        _info = _sdb.refresh_token(rtoken)
Esempio n. 26
0
 def test_token_type(self):
     # lacks required token_type parameter
     _info = {"access_token": "accessTok", "id_token": "blabla"}
     at = AccessTokenResponse(**_info)
     with pytest.raises(MissingRequiredAttribute):
         at.verify()
Esempio n. 27
0
    def test_full_flow(self, context, frontend):
        redirect_uri = "https://client.example.com/redirect"
        response_type = "code id_token token"
        mock_callback = Mock()
        frontend.auth_req_callback_func = mock_callback
        # discovery
        http_response = frontend.provider_config(context)
        provider_config = ProviderConfigurationResponse().deserialize(
            http_response.message, "json")

        # client registration
        registration_request = RegistrationRequest(
            redirect_uris=[redirect_uri], response_types=[response_type])
        context.request = registration_request.to_dict()
        http_response = frontend.client_registration(context)
        registration_response = RegistrationResponse().deserialize(
            http_response.message, "json")

        # authentication request
        authn_req = AuthorizationRequest(
            redirect_uri=redirect_uri,
            client_id=registration_response["client_id"],
            response_type=response_type,
            scope="openid email",
            state="state",
            nonce="nonce")
        context.request = dict(parse_qsl(authn_req.to_urlencoded()))
        frontend.handle_authn_request(context)
        assert mock_callback.call_count == 1

        # fake authentication response from backend
        internal_response = self.setup_for_authn_response(
            context, frontend, authn_req)
        http_response = frontend.handle_authn_response(context,
                                                       internal_response)
        authn_resp = AuthorizationResponse().deserialize(
            urlparse(http_response.message).fragment, "urlencoded")
        assert "code" in authn_resp
        assert "access_token" in authn_resp
        assert "id_token" in authn_resp

        # token request
        context.request = AccessTokenRequest(
            redirect_uri=authn_req["redirect_uri"],
            code=authn_resp["code"]).to_dict()
        credentials = "{}:{}".format(registration_response["client_id"],
                                     registration_response["client_secret"])
        basic_auth = urlsafe_b64encode(
            credentials.encode("utf-8")).decode("utf-8")
        context.request_authorization = "Basic {}".format(basic_auth)

        http_response = frontend.token_endpoint(context)
        parsed = AccessTokenResponse().deserialize(http_response.message,
                                                   "json")
        assert "access_token" in parsed
        assert "id_token" in parsed

        # userinfo request
        context.request = {}
        context.request_authorization = "Bearer {}".format(
            parsed["access_token"])
        http_response = frontend.userinfo_endpoint(context)
        parsed = OpenIDSchema().deserialize(http_response.message, "json")
        assert "email" in parsed
Esempio n. 28
0
            _sdb.revoke_all_tokens(_access_code)
            return self._error(environ, start_response,
                               error="access_denied", descr= "%s" % err)

        if "openid" in _info["scope"]:
            try:
                _idtoken = self._id_token(_info)
            except AccessDenied:
                return self._error(environ, start_response,
                                   error="access_denied")

            _sdb.update_by_token(_access_code, "id_token", _idtoken)

        _log_debug("_tinfo: %s" % _tinfo)

        atr = AccessTokenResponse(**by_schema(AccessTokenResponse, **_tinfo))

        if self.test_mode:
            _log_info("access_token_response: %s" % atr.to_dict())

        resp = Response(atr.to_json(), content="application/json")
        return resp(environ, start_response)

    def _bearer_auth(self, environ):
        #'HTTP_AUTHORIZATION': 'Bearer pC7efiVgbI8UASlolltdh76DrTZ2BQJQXFhVvwWlKekFvWCcdMTmNCI/BCSCxQiG'
        try:
            authn = environ["HTTP_AUTHORIZATION"]
            try:
                assert authn[:6].lower() == "bearer"
                _token = authn[7:]
            except AssertionError:
    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')