Beispiel #1
0
    def _pre_construct(self, response_args, request, **kwargs):
        _context = self.endpoint_context
        _access_code = request["code"].replace(' ', '+')
        _info = _context.sdb[_access_code]
        _authn_req = _info['authn_req']
        try:
            _client_id = request['client_id']
        except KeyError:
            _client_id = _authn_req['client_id']

        if "openid" in _authn_req["scope"]:
            userinfo = userinfo_in_id_token_claims(_context, _info)
            try:
                _idtoken = sign_encrypt_id_token(_context, _info,
                                                 str(_client_id),
                                                 user_info=userinfo)
            except (JWEException, NoSuitableSigningKeys) as err:
                logger.warning(str(err))
                return self.error_cls(
                    error="invalid_request",
                    error_description="Could not sign/encrypt id_token")

            _context.sdb.update_by_token(_access_code, id_token=_idtoken)
            response_args['id_token'] = _idtoken

        return response_args
Beispiel #2
0
    def make(self,
             req,
             sess_info,
             authn_req=None,
             user_claims=False,
             **kwargs):
        _context = self.endpoint_context
        _sdb = _context.sdb

        if authn_req:
            _client_id = authn_req["client_id"]
        else:
            _client_id = req["client_id"]

        _cinfo = _context.cdb[_client_id]
        try:
            default_idtoken_claims = self.kwargs["default_claims"]
        except KeyError:
            default_idtoken_claims = None

        lifetime = self.kwargs.get("lifetime")

        userinfo = userinfo_in_id_token_claims(_context, sess_info,
                                               default_idtoken_claims)

        if user_claims:
            info = collect_user_info(_context, sess_info)
            if userinfo is None:
                userinfo = info
            else:
                userinfo.update(info)

        try:
            req_sid = _cinfo["frontchannel_logout_session_required"]
        except KeyError:
            try:
                req_sid = _cinfo["backchannel_logout_session_required"]
            except KeyError:
                req_sid = False

        if req_sid:
            xargs = {
                "sid":
                _context.sdb.get_sid_by_sub_and_client_id(
                    sess_info["sub"], _client_id)
            }
        else:
            xargs = {}

        return self.sign_encrypt(sess_info,
                                 _client_id,
                                 sign=True,
                                 user_info=userinfo,
                                 lifetime=lifetime,
                                 extra_claims=xargs,
                                 **kwargs)
Beispiel #3
0
    def make(self,
             req,
             sess_info,
             authn_req=None,
             user_claims=False,
             **kwargs):
        _context = self.endpoint_context
        _sdb = _context.sdb

        if authn_req:
            _client_id = authn_req["client_id"]
        else:
            _client_id = req["client_id"]

        _cinfo = _context.cdb[_client_id]

        default_idtoken_claims = dict(self.kwargs.get("default_claims", {}))
        lifetime = self.kwargs.get("lifetime")

        userinfo = userinfo_in_id_token_claims(_context, sess_info,
                                               default_idtoken_claims)

        if user_claims:
            info = collect_user_info(_context, sess_info)
            if userinfo is None:
                userinfo = info
            else:
                userinfo.update(info)

        # Should I add session ID
        req_sid = include_session_id(_context, _client_id,
                                     "back") or include_session_id(
                                         _context, _client_id, "front")

        if req_sid:
            xargs = {
                "sid":
                _context.sdb.get_sid_by_sub_and_client_id(
                    sess_info["sub"], _client_id)
            }
        else:
            xargs = {}

        return self.sign_encrypt(sess_info,
                                 _client_id,
                                 sign=True,
                                 user_info=userinfo,
                                 lifetime=lifetime,
                                 extra_claims=xargs,
                                 **kwargs)
Beispiel #4
0
def create_authn_response(endpoint_context, request, sid):
    # create the response
    aresp = AuthorizationResponse()
    try:
        aresp["state"] = request["state"]
    except KeyError:
        pass

    if "response_type" in request and request["response_type"] == ["none"]:
        fragment_enc = False
    else:
        _sinfo = endpoint_context.sdb[sid]

        try:
            aresp["scope"] = request["scope"]
        except KeyError:
            pass

        rtype = set(request["response_type"][:])
        handled_response_type = []
        if len(rtype) == 1 and "code" in rtype:
            fragment_enc = False
        else:
            fragment_enc = True

        if "code" in request["response_type"]:
            _code = aresp["code"] = endpoint_context.sdb[sid]["code"]
            handled_response_type.append("code")
        else:
            endpoint_context.sdb.update(sid, code=None)
            _code = None

        if "token" in rtype:
            _dic = endpoint_context.sdb.upgrade_to_token(issue_refresh=False,
                                                         key=sid)

            logger.debug("_dic: %s" % sanitize(_dic))
            for key, val in _dic.items():
                if key in aresp.parameters() and val is not None:
                    aresp[key] = val

            handled_response_type.append("token")

        try:
            _access_token = aresp["access_token"]
        except KeyError:
            _access_token = None

        if "id_token" in request["response_type"]:
            user_info = userinfo_in_id_token_claims(endpoint_context, _sinfo)
            if request["response_type"] == ["id_token"]:
                #  scopes should be returned here
                info = collect_user_info(endpoint_context, _sinfo)
                if user_info is None:
                    user_info = info
                else:
                    user_info.update(info)

            # client_info = endpoint_context.cdb[str(request["client_id"])]

            hargs = {}
            if {'code', 'id_token', 'token'}.issubset(rtype):
                hargs = {"code": _code, "access_token": _access_token}
            elif {'code', 'id_token'}.issubset(rtype):
                hargs = {"code": _code}
            elif {'id_token', 'token'}.issubset(rtype):
                hargs = {"access_token": _access_token}

            # or 'code id_token'
            try:
                id_token = sign_encrypt_id_token(endpoint_context, _sinfo,
                                                 str(request["client_id"]),
                                                 user_info=user_info,
                                                 sign=True, **hargs)
            except (JWEException, NoSuitableSigningKeys) as err:
                logger.warning(str(err))
                return AuthorizationErrorResponse(
                    error="invalid_request",
                    error_description="Could not sign/encrypt id_token")

            aresp["id_token"] = id_token
            _sinfo["id_token"] = id_token
            handled_response_type.append("id_token")

        not_handled = rtype.difference(handled_response_type)
        if not_handled:
            raise UnSupported("unsupported_response_type", list(not_handled))

    return {'response_args': aresp, 'fragment_enc': fragment_enc}
Beispiel #5
0
    def _access_token(self, req, **kwargs):
        _context = self.endpoint_context
        _sdb = _context.sdb
        _log_debug = logger.debug

        if req["grant_type"] != "authorization_code":
            return self.error_cls(error='invalid_request',
                                  error_description='Unknown grant_type')

        try:
            _access_code = req["code"].replace(' ', '+')
        except KeyError:  # Missing code parameter - absolutely fatal
            return self.error_cls(error='invalid_request',
                                  error_description='Missing code')

        # Session might not exist or _access_code malformed
        try:
            _info = _sdb[_access_code]
        except KeyError:
            return self.error_cls(error="invalid_request",
                                  error_description="Code is invalid")

        _authn_req = _info['authn_req']

        # assert that the code is valid
        if _context.sdb.is_session_revoked(_access_code):
            return self.error_cls(error="invalid_request",
                                  error_description="Session is revoked")

        # If redirect_uri was in the initial authorization request
        # verify that the one given here is the correct one.
        if "redirect_uri" in _authn_req:
            if req["redirect_uri"] != _authn_req["redirect_uri"]:
                return self.error_cls(error="invalid_request",
                                      error_description="redirect_uri mismatch")

        _log_debug("All checks OK")

        issue_refresh = False
        if "issue_refresh" in kwargs:
            issue_refresh = kwargs["issue_refresh"]

        # offline_access the default if nothing is specified
        permissions = _info.get('permission', ['offline_access'])

        if 'offline_access' in _authn_req['scope'] and 'offline_access' in permissions:
            issue_refresh = True

        try:
            _info = _sdb.upgrade_to_token(_access_code,
                                          issue_refresh=issue_refresh)
        except AccessCodeUsed as err:
            logger.error("%s" % err)
            # Should revoke the token issued to this access code
            _sdb.revoke_all_tokens(_access_code)
            return self.error_cls(error="access_denied",
                                  error_description="Access Code already used")

        if "openid" in _authn_req["scope"]:
            userinfo = userinfo_in_id_token_claims(_context, _info)

            try:
                _client_id = req['client_id']
            except KeyError:
                _client_id = _authn_req['client_id']

            try:
                _idtoken = sign_encrypt_id_token(_context, _info, _client_id,
                                                 sign=True, user_info=userinfo)
            except (JWEException, NoSuitableSigningKeys) as err:
                logger.warning(str(err))
                return self.error_cls(
                    error="invalid_request",
                    error_description="Could not sign/encrypt id_token")

            _sdb.update_by_token(_access_code, id_token=_idtoken)
            _info = _sdb[_access_code]

        return by_schema(AccessTokenResponse, **_info)