-
Notifications
You must be signed in to change notification settings - Fork 49
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
First attempt at implementing 'OAuth2 for first party apps'
- Loading branch information
Showing
18 changed files
with
498 additions
and
48 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
{ | ||
"$schema": "https://json-schema.org/draft/2019-09/schema", | ||
"$id": "https://curveballjs.org/schemas/a12nserver/authorization-challenge-request.json", | ||
"type": "object", | ||
"title": "AuthorizationChallengeRequest", | ||
"description": "Request body for the Authorization Challenge Request endpoint for first-party applications.", | ||
"required": [], | ||
"additionalProperties": false, | ||
|
||
"properties": { | ||
"scope": { | ||
"type": "string", | ||
"description": "OAuth2 scope" | ||
}, | ||
"auth_session": { | ||
"description": "If the client has started a login session, specify auth_session to continue the login process", | ||
"type": "string" | ||
}, | ||
"username": { | ||
"type": "string" | ||
}, | ||
"password": { | ||
"type": "string" | ||
} | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { dirname } from 'node:path'; | ||
import { fileURLToPath } from 'node:url'; | ||
|
||
/** | ||
* This file exists to ensure that .env is loaded as early as possible. | ||
* Anything that needs it should import it | ||
*/ | ||
import * as dotenv from 'dotenv'; | ||
|
||
if (process.env.PUBLIC_URI === undefined) { | ||
// If there's no PUBLIC_URI environment variable, it's a good indication | ||
// that we may be missing a .env file. | ||
// | ||
// This is the only required environment variable. | ||
dotenv.config({path: dirname(fileURLToPath(import.meta.url)) + '/../.env'}); | ||
} else { | ||
console.warn('/env.js was loaded twice?'); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import { Controller } from '@curveball/controller'; | ||
import { Context } from '@curveball/kernel'; | ||
import { getOAuth2ClientFromBasicAuth } from '../../app-client/service.js'; | ||
import { UnauthorizedClient } from '../../oauth2/errors.js'; | ||
import { UnsupportedMediaType } from '@curveball/http-errors'; | ||
import { AuthorizationChallengeRequest } from '../../api-types.js'; | ||
import * as loginService from '../service.js'; | ||
|
||
/** | ||
* The authorization challenge controller is an implementation of OAuth 2.0 | ||
* for First-Party Applications. | ||
* | ||
* This specification is currently a draft, and so this endpoint will also | ||
* evolve as the specification evolves. | ||
* | ||
* The endpoint lets a first party, trusted app authenticate with an OAuth2 | ||
* server and completely own UI. | ||
* | ||
* It's implemented as a series of requests and challenges until all | ||
* challenges are met. For example, a first challenge may be a password, a | ||
* second a TOTP token. Once there are no more challenges, a 'code' gets | ||
* returned which may be exchanged for a 'token' on the token endpoint. | ||
* | ||
* https://www.ietf.org/archive/id/draft-parecki-oauth-first-party-apps-00.html | ||
* | ||
*/ | ||
class AuthorizationChallengeController extends Controller { | ||
|
||
async post(ctx: Context) { | ||
|
||
// We will only support Basic auth for now. | ||
const client = await getOAuth2ClientFromBasicAuth(ctx); | ||
|
||
if (!client.allowedGrantTypes.includes('authorization_challenge')) { | ||
throw new UnauthorizedClient('This client is not allowed to use the "authorization_challenge" oauth2 flow'); | ||
} | ||
|
||
if (!ctx.request.is('application/x-www-form-urlencoded')) { | ||
throw new UnsupportedMediaType('This endpoint requires thei request to use the "application/x-www-form-urlencoded" content-type'); | ||
} | ||
|
||
ctx.request.validate<AuthorizationChallengeRequest>('https://curveballjs.org/schemas/a12nserver/authorization-challenge-request.json'); | ||
|
||
const request = ctx.request.body; | ||
|
||
const session = await loginService.getSession(client, request); | ||
const code = await loginService.challenge(client, session, request); | ||
|
||
ctx.response.body = { | ||
authorization_code: code.code, | ||
}; | ||
|
||
} | ||
|
||
} | ||
|
||
|
||
|
||
export default new AuthorizationChallengeController(); |
Oops, something went wrong.