-
-
Notifications
You must be signed in to change notification settings - Fork 4.7k
Implement basic OIDC core server handling #12567
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -35,6 +35,8 @@ | |
| use OCP\AppFramework\Http\JSONResponse; | ||
| use OCP\AppFramework\Utility\ITimeFactory; | ||
| use OCP\IRequest; | ||
| use OCP\IURLGenerator; | ||
| use OCP\IUserManager; | ||
| use OCP\Security\ICrypto; | ||
| use OCP\Security\ISecureRandom; | ||
|
|
||
|
|
@@ -53,6 +55,10 @@ class OauthApiController extends Controller { | |
| private $time; | ||
| /** @var Throttler */ | ||
| private $throttler; | ||
| /** @var IUserManager */ | ||
| private $userManager; | ||
| /** @var IURLGenerator */ | ||
| private $urlGenerator; | ||
|
|
||
| public function __construct(string $appName, | ||
| IRequest $request, | ||
|
|
@@ -62,7 +68,9 @@ public function __construct(string $appName, | |
| TokenProvider $tokenProvider, | ||
| ISecureRandom $secureRandom, | ||
| ITimeFactory $time, | ||
| Throttler $throttler) { | ||
| Throttler $throttler, | ||
| IUserManager $userManager, | ||
| IURLGenerator $urlGenerator) { | ||
| parent::__construct($appName, $request); | ||
| $this->crypto = $crypto; | ||
| $this->accessTokenMapper = $accessTokenMapper; | ||
|
|
@@ -71,6 +79,8 @@ public function __construct(string $appName, | |
| $this->secureRandom = $secureRandom; | ||
| $this->time = $time; | ||
| $this->throttler = $throttler; | ||
| $this->userManager = $userManager; | ||
| $this->urlGenerator = $urlGenerator; | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -161,6 +171,7 @@ public function getToken($grant_type, $code, $refresh_token, $client_id, $client | |
| $this->accessTokenMapper->update($accessToken); | ||
|
|
||
| $this->throttler->resetDelay($this->request->getRemoteAddress(), 'login', ['user' => $appToken->getUID()]); | ||
| $jwt = $this->getIdToken($client_id, $appToken, $client); | ||
|
|
||
| return new JSONResponse( | ||
| [ | ||
|
|
@@ -169,7 +180,66 @@ public function getToken($grant_type, $code, $refresh_token, $client_id, $client | |
| 'expires_in' => 3600, | ||
| 'refresh_token' => $newCode, | ||
| 'user_id' => $appToken->getUID(), | ||
| 'id_token' => $jwt, | ||
| ] | ||
| ); | ||
| } | ||
|
|
||
| /** | ||
| * @param $client_id | ||
| * @param \OC\Authentication\Token\IToken $appToken | ||
| * @param \OCA\OAuth2\Db\Client $client | ||
| * @return string | ||
| */ | ||
| private function getIdToken($client_id, \OC\Authentication\Token\IToken $appToken, \OCA\OAuth2\Db\Client $client) | ||
| { | ||
| // The id token needs to be correctly build as JWT. Taken from https://dev.to/robdwaller/how-to-create-a-json-web-token-using-php-3gml | ||
|
|
||
| // Create token header as a JSON string | ||
| $header = json_encode(['typ' => 'JWT', 'alg' => 'HS256']); | ||
|
|
||
| // We need the user to fill in name and email in the id_token | ||
| $user = $this->userManager->get($appToken->getUID()); | ||
|
|
||
| // Create token payload as a JSON string | ||
| $payload = json_encode([ | ||
tisoft marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| // required for OIDC, see https://openid.net/specs/openid-connect-core-1_0.html#IDToken | ||
| // Issuer Identifier for the Issuer of the response. | ||
| 'iss' => $this->urlGenerator->getBaseUrl(), | ||
| // Subject Identifier. A locally unique and never reassigned identifier within the Issuer for the End-User, which is intended to be consumed by the Client | ||
| 'sub' => $appToken->getUID(), | ||
| // Audience(s) that this ID Token is intended for. It MUST contain the OAuth 2.0 client_id of the Relying Party as an audience value. | ||
| 'aud' => $client_id, | ||
| // Expiration time on or after which the ID Token MUST NOT be accepted for processing. | ||
| 'exp' => $appToken->getExpires(), | ||
| // Time at which the JWT was issued. | ||
| 'iat' => $this->time->getTime(), | ||
| // Time when the End-User authentication occurred. | ||
| 'auth_time' => $this->time->getTime(), | ||
|
|
||
| // optional, can be requested by claims, we don't support requesting claims as of now, so we just send them always | ||
| // see https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims | ||
| // End-User's preferred e-mail address. | ||
| 'email' => $user->getEMailAddress(), | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it a problem if those are empty?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As I understand it, they can be left empty. |
||
| // End-User's full name in displayable form including all name parts, possibly including titles and suffixes | ||
| 'name' => $user->getDisplayName(), | ||
|
|
||
| ]); | ||
|
|
||
| // Encode Header to Base64Url String | ||
| $base64UrlHeader = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($header)); | ||
|
|
||
| // Encode Payload to Base64Url String | ||
| $base64UrlPayload = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($payload)); | ||
|
|
||
| // Create Signature Hash | ||
| $signature = hash_hmac('sha256', $base64UrlHeader . "." . $base64UrlPayload, $client->getSecret(), true); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So the signature is required it seems. But how can it every be validated?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The OpenID Connect client will do the same hash calculation on his side. Since the client knows the oauth client secret he can do that. That way the signature can be verified. |
||
|
|
||
| // Encode Signature to Base64Url String | ||
| $base64UrlSignature = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($signature)); | ||
|
|
||
| // Create JWT | ||
| $jwt = $base64UrlHeader . "." . $base64UrlPayload . "." . $base64UrlSignature; | ||
| return $jwt; | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.