client = $client; } /** * Get the URL the user should be redirected to to begin the authorization process. * * @param string $redirect_uri url the oidc endpoint should redirect the user back to; generally must be authorized in the provider * @param string[] $scopes the scopes to request in the token * @return string url to redirect the user to */ public function getRedirectUrl(string $redirect_uri, array $scopes = ['email']): string { // Generate nonce // We use 30 because that should generate an even number of base64 characters // and not require padding. (6 bits / char) $state = base64_encode(random_bytes(30)); // Keep a list of all valid states we've generated $states = Authkit2::session_get('userflow.state') ?? []; array_push($states, $state); Authkit2::session_set('userflow.state', $states); return $this->client->createAuthorizationRedirectUrl($redirect_uri, $scopes, $state); } /** * Validate that the provided state string is one we have previously generated. * * @param string $state * @throws \Exception if the state is unrecognized or invalid * @return void */ public function validateState(string $state): void { $states = Authkit2::session_get('userflow.state') ?? []; for ($i = 0; $i < sizeof($states); $i++) { if ($states[$i] == $state) { $states = array_splice($states, $i, 1); Authkit2::session_set('userflow.state', $states); return; } } throw new \Exception('Invalid auth nonce'); } /** * After the user is redirected back with a authorization code, exchange it * for an access token. * * THIS DOES NOT VALIDATE THE STATE. Call validateState first. * * @param string $code code returned by the authorization flow * @param string $redirect_uri url the oidc endpoint redirects back to; must match one given in call to getRedirectUrl * @return Token */ public function exchangeCodeForToken(string $code, string $redirect_uri): Token { return $this->client->createTokenFromAuthorizationCode($code, $redirect_uri); } /** * If we want to log out of the SSO service and all apps, the URL to hit to * sign out everywhere. * * @param string $redirect_uri url to redirect back to after logout completes * @return string */ public function getLogoutUrl(string $redirect_uri): string { return $this->client->createLogoutUrl($redirect_uri); } }