diff --git a/src/http-api.ts b/src/http-api.ts index f5c682d..3523d70 100644 --- a/src/http-api.ts +++ b/src/http-api.ts @@ -376,19 +376,46 @@ export class HttpApi { #setupWeb5ConnectServerRoutes(): void { /** - * Endpoint that the connecting App pushes the Pushed Authorization Request Object to start the Web5 Connect flow. - */ + * Endpoint allows a Client app (RP) to submit an Authorization Request. + * The Authorization Request is stored on the server, and a unique `request_uri` is returned to the Client app. + * The Client app can then provide this `request_uri` to the Provider app (wallet). + * The Provider app uses the `request_uri` to retrieve the stored Authorization Request. + */ this.#api.post('/connect/par', async (req, res) => { log.info('Storing Pushed Authorization Request (PAR) request...'); + // TODO: Add validation for request too large HTTP 413: https://github.com/TBD54566975/dwn-server/issues/146 + // TODO: Add validation for too many requests HTTP 429: https://github.com/TBD54566975/dwn-server/issues/147 + + if (!req.body.request) { + return res.status(400).json({ + ok: false, + status: { + code: 400, + message: "Bad Request: Missing 'request' parameter", + }, + }); + } + + // Validate that `request_uri` was NOT provided + if (req.body?.request?.request_uri) { + return res.status(400).json({ + ok: false, + status: { + code: 400, + message: "Bad Request: 'request_uri' parameter is not allowed in PAR", + }, + }); + } + const result = await this.web5ConnectServer.setWeb5ConnectRequest(req.body.request); res.status(201).json(result); }); /** - * Endpoint that the Identity Provider (wallet) calls to retrieve the Pushed Authorization Request. - */ - this.#api.get('/connect/:requestId.jwt', async (req, res) => { + * Endpoint for the Provider to retrieve the Authorization Request from the request_uri + */ + this.#api.get('/connect/authorize/:requestId.jwt', async (req, res) => { log.info(`Retrieving Web5 Connect Request object of ID: ${req.params.requestId}...`); // Look up the request object based on the requestId. @@ -406,9 +433,9 @@ export class HttpApi { }); /** - * Endpoint that the Identity Provider (wallet) pushes the Authorization Response ID token to. - */ - this.#api.post('/connect/sessions', async (req, res) => { + * Endpoint that the Provider sends the Authorization Response to + */ + this.#api.post('/connect/callback', async (req, res) => { log.info('Storing Identity Provider (wallet) pushed response with ID token...'); // Store the ID token. @@ -433,10 +460,9 @@ export class HttpApi { }); /** - * Endpoint that the connecting App polls to check if the Identity Provider (Wallet) has posted the Web5 Connect Response object. - * The Web5 Connect Response is also an ID token. - */ - this.#api.get('/connect/sessions/:state.jwt', async (req, res) => { + * Endpoint for the connecting Client to retrieve the Authorization Response + */ + this.#api.get('/connect/token/:state.jwt', async (req, res) => { log.info(`Retrieving ID token for state: ${req.params.state}...`); // Look up the ID token. diff --git a/src/web5-connect/web5-connect-server.ts b/src/web5-connect/web5-connect-server.ts index 007faa7..72ff1e6 100644 --- a/src/web5-connect/web5-connect-server.ts +++ b/src/web5-connect/web5-connect-server.ts @@ -68,7 +68,7 @@ export class Web5ConnectServer { public async setWeb5ConnectRequest(request: Web5ConnectRequest): Promise { // Generate a request URI const requestId = randomUuid(); - const request_uri = `${this.baseUrl}/connect/${requestId}.jwt`; + const request_uri = `${this.baseUrl}/connect/authorize/${requestId}.jwt`; // Store the Request Object. this.cache.insert(`request:${requestId}`, request, Web5ConnectServer.ttlInSeconds); diff --git a/tests/scenarios/web5-connect.spec.ts b/tests/scenarios/web5-connect.spec.ts index 969c5ab..3533600 100644 --- a/tests/scenarios/web5-connect.spec.ts +++ b/tests/scenarios/web5-connect.spec.ts @@ -93,7 +93,7 @@ describe('Web5 Connect scenarios', function () { id_token : { dummyToken: 'dummyToken' }, // state : 'dummyState', // intentionally missing }; - const postIncompleteWeb5ConnectResponseResult = await fetch(`${web5ConnectBaseUrl}/connect/sessions`, { + const postIncompleteWeb5ConnectResponseResult = await fetch(`${web5ConnectBaseUrl}/connect/callback`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(incompleteResponseBody), @@ -106,7 +106,7 @@ describe('Web5 Connect scenarios', function () { id_token : { dummyToken: 'dummyToken' }, state }; - const postWeb5ConnectResponseResult = await fetch(`${web5ConnectBaseUrl}/connect/sessions`, { + const postWeb5ConnectResponseResult = await fetch(`${web5ConnectBaseUrl}/connect/callback`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(web5ConnectResponseBody), @@ -114,7 +114,7 @@ describe('Web5 Connect scenarios', function () { expect(postWeb5ConnectResponseResult.status).to.equal(201); // 6. App fetches the Web5 Connect Response object from the Web5 Connect server. - const web5ConnectResponseUrl = `${web5ConnectBaseUrl}/connect/sessions/${web5ConnectResponseBody.state}.jwt`; + const web5ConnectResponseUrl = `${web5ConnectBaseUrl}/connect/token/${web5ConnectResponseBody.state}.jwt`; let getWeb5ConnectResponseResult; await Poller.pollUntilSuccessOrTimeout(async () => {