def create_authorization_url(self, url, state=None, **kwargs): """Generate an authorization URL and state. :param url: Authorization endpoint url, must be HTTPS. :param state: An optional state string for CSRF protection. If not given it will be generated for you. :param kwargs: Extra parameters to include. :return: authorization_url, state """ state = state or self.state if state is None: state = generate_token() response_type = self._kwargs.get('response_type', 'code') response_type = kwargs.pop('response_type', response_type) if 'redirect_uri' not in kwargs: kwargs['redirect_uri'] = self.redirect_uri if 'scope' not in kwargs: kwargs['scope'] = self.scope # Add OIDC optional parameters oidc_params = ['response_mode', 'nonce', 'prompt', 'login_hint'] for k in oidc_params: if k not in kwargs and k in self._kwargs: kwargs[k] = self._kwargs[k] uri = prepare_grant_uri( url, client_id=self.client_id, response_type=response_type, state=state, **kwargs) return uri, state
async def handle_redirect_request( self, request: SynapseRequest, client_redirect_url: bytes ) -> None: """Handle an incoming request to /login/sso/redirect It redirects the browser to the authorization endpoint with a few parameters: - ``client_id``: the client ID set in ``oidc_config.client_id`` - ``response_type``: ``code`` - ``redirect_uri``: the callback URL ; ``{base url}/_synapse/oidc/callback`` - ``scope``: the list of scopes set in ``oidc_config.scopes`` - ``state``: a random string - ``nonce``: a random string In addition to redirecting the client, we are setting a cookie with a signed macaroon token containing the state, the nonce and the client_redirect_url params. Those are then checked when the client comes back from the provider. Args: request: the incoming request from the browser. We'll respond to it with a redirect and a cookie. client_redirect_url: the URL that we should redirect the client to when everything is done """ state = generate_token() nonce = generate_token() cookie = self._generate_oidc_session_token( state=state, nonce=nonce, client_redirect_url=client_redirect_url.decode(), ) request.addCookie( SESSION_COOKIE_NAME, cookie, path="/_synapse/oidc", max_age="3600", httpOnly=True, sameSite="lax", ) metadata = await self.load_metadata() authorization_endpoint = metadata.get("authorization_endpoint") uri = prepare_grant_uri( authorization_endpoint, client_id=self._client_auth.client_id, response_type="code", redirect_uri=self._callback_url, scope=self._scopes, state=state, nonce=nonce, ) request.redirect(uri) finish_request(request)
async def handle_redirect_request( self, request: SynapseRequest, client_redirect_url: Optional[bytes], ui_auth_session_id: Optional[str] = None, ) -> str: """Handle an incoming request to /login/sso/redirect It returns a redirect to the authorization endpoint with a few parameters: - ``client_id``: the client ID set in ``oidc_config.client_id`` - ``response_type``: ``code`` - ``redirect_uri``: the callback URL ; ``{base url}/_synapse/client/oidc/callback`` - ``scope``: the list of scopes set in ``oidc_config.scopes`` - ``state``: a random string - ``nonce``: a random string In addition generating a redirect URL, we are setting a cookie with a signed macaroon token containing the state, the nonce and the client_redirect_url params. Those are then checked when the client comes back from the provider. Args: request: the incoming request from the browser. We'll respond to it with a redirect and a cookie. client_redirect_url: the URL that we should redirect the client to when everything is done (or None for UI Auth) ui_auth_session_id: The session ID of the ongoing UI Auth (or None if this is a login). Returns: The redirect URL to the authorization endpoint. """ state = generate_token() nonce = generate_token() if not client_redirect_url: client_redirect_url = b"" cookie = self._token_generator.generate_oidc_session_token( state=state, session_data=OidcSessionData( idp_id=self.idp_id, nonce=nonce, client_redirect_url=client_redirect_url.decode(), ui_auth_session_id=ui_auth_session_id, ), ) request.addCookie( SESSION_COOKIE_NAME, cookie, path="/_synapse/client/oidc", max_age="3600", httpOnly=True, sameSite="lax", ) metadata = await self.load_metadata() authorization_endpoint = metadata.get("authorization_endpoint") return prepare_grant_uri( authorization_endpoint, client_id=self._client_auth.client_id, response_type="code", redirect_uri=self._callback_url, scope=self._scopes, state=state, nonce=nonce, )