juanifioren / django-oidc-provider

OpenID Connect and OAuth2 provider implementation for Djangonauts.
http://django-oidc-provider.readthedocs.org
MIT License
425 stars 239 forks source link

insufficient_scope, although scope was granted #417

Closed markus-96 closed 1 month ago

markus-96 commented 10 months ago

I try to implement a little openid-connect client, with django-oidc-provider as provider. The problem is that it seems like I do not have sufficient rights to get them via userinfo.

The following snippet does only give these headers:

<CIMultiDictProxy('Date': 'Sun, 07 Jan 2024 00:50:13 GMT', 'Server': 'WSGIServer/0.2 CPython/3.12.1', 'Content-Type': 'text/html; charset=utf-8', 'WWW-Authenticate': 'error="insufficient_scope", error_description="The request requires higher privileges than provided by the access token"', 'X-Frame-Options': 'DENY', 'Content-Length': '0', 'Set-Cookie': 'op_browser_state=7677442bd758c1ca1091127d0acb28d31a5e7bc4fa3b5aac86b7564b; Path=/')>

And my code:

    async def get_user_info_two(self, authorization_code: str, *args, **kwargs):
        payload = {
            "grant_type": "authorization_code",
            "client_id": self.__client_id,
            "client_secret": self.__client_secret,
            "code": authorization_code,
            "redirect_uri": "https://localhost/oauth/django-oidc2"
        }
        headers = {"content-type": "application/x-www-form-urlencoded"}
        async with aiohttp.ClientSession() as session:
            # get access_token:
            async with session.post(self.__access_token_url, data=payload, headers=headers) as resp:
                token_data = await resp.json()
                token = token_data.get("access_token")
                access_token = token

            headers = {
                "Cache-Control": "no-cache",
            }
            payload = {
                "access_token": access_token
            }
            # get userinfo:
            async with session.get(f"{self.__user_info_url}?{urlencode(payload)}", headers=headers) as response:
                text = response.headers
                logging.warning(text)
                user_info = await response.json()
                return user_info

At retrieving the access_token, I explicitly tell it to ask for the scope "profile". On the website, I also grant to access the scope. The access_token should not be the problem I think.

Oh, and this is how I generate the authorize_url

    def get_authorize_url(self, **kwargs) -> str:
        """
        Generates the Authorization-Code-Request (Step 2)
        """
        params = dict(self.__params)
        params.update({"client_id": self.__client_id, "response_type": "code", "scope": "profile"})
        return f"{self.__authorize_url}?{urlencode(params)}"

I have no idea what I am doing wrong.

PS: This code is not ready to use yet, I know it is horrible..

juanifioren commented 1 month ago

@markus-96 you are missing openid in scopes since is required by the protocol. Source