Skip to content

Commit 6f86509

Browse files
committed
feat: Move JSON conversion away from route handlers
� Conflicts: � packages/uma/src/routes/Ticket.ts
1 parent 06f2031 commit 6f86509

18 files changed

Lines changed: 260 additions & 269 deletions

packages/uma/.componentsignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"AccessToken",
44
"Authorization",
55
"Authorizer",
6+
"Buffer",
67
"Error",
78
"EventEmitter",
89
"Map",
@@ -13,5 +14,6 @@
1314
"ReType",
1415
"ScopeDescription",
1516
"Ticket",
16-
"URL"
17+
"URL",
18+
"WeakMap"
1719
]

packages/uma/bin/demo.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export const launch: () => Promise<void> = async () => {
3838
await manager.configRegistry.register(configPath);
3939

4040
const umaServer: ServerInitializer = await manager.instantiate('urn:uma:default:NodeHttpServer',{variables});
41-
await umaServer.handle();
41+
await umaServer.handleSafe();
4242

4343
};
4444

packages/uma/bin/main.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export const launch: () => Promise<void> = async () => {
3838
await manager.configRegistry.register(configPath);
3939

4040
const umaServer: ServerInitializer = await manager.instantiate('urn:uma:default:NodeHttpServer',{variables});
41-
await umaServer.handle();
41+
await umaServer.handleSafe();
4242

4343
};
4444

packages/uma/config/default.json

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -85,22 +85,26 @@
8585
"includeQueryString": true
8686
},
8787
"httpHandler": {
88-
"@id": "urn:uma:default:RoutedHttpRequestHandler",
89-
"@type": "RoutedHttpRequestHandler",
90-
"routes": [
91-
{ "@id": "urn:uma:default:UmaConfigRoute" },
92-
{ "@id": "urn:uma:default:JwksRoute" },
93-
{ "@id": "urn:uma:default:DemoTokenRoute" },
94-
{ "@id": "urn:uma:default:PermissionRegistrationRoute" },
95-
{ "@id": "urn:uma:default:ResourceRegistrationRoute" },
96-
{ "@id": "urn:uma:default:ResourceRegistrationOpsRoute" },
97-
{ "@id": "urn:uma:default:IntrospectionRoute" },
88+
"@id": "urm:uma:default:JsonFormHttpHandler",
89+
"@type": "JsonFormHttpHandler",
90+
"handler": {
91+
"@id": "urn:uma:default:RoutedHttpRequestHandler",
92+
"@type": "RoutedHttpRequestHandler",
93+
"routes": [
94+
{ "@id": "urn:uma:default:UmaConfigRoute" },
95+
{ "@id": "urn:uma:default:JwksRoute" },
96+
{ "@id": "urn:uma:default:DemoTokenRoute" },
97+
{ "@id": "urn:uma:default:PermissionRegistrationRoute" },
98+
{ "@id": "urn:uma:default:ResourceRegistrationRoute" },
99+
{ "@id": "urn:uma:default:ResourceRegistrationOpsRoute" },
100+
{ "@id": "urn:uma:default:IntrospectionRoute" },
98101
{ "@id": "urn:uma:default:LogRoute" },
99102
{ "@id": "urn:uma:default:VCRoute" },
100103
{ "@id": "urn:uma:default:ContractRoute" }
101-
],
102-
"defaultHandler": {
103-
"@type": "DefaultRequestHandler"
104+
],
105+
"defaultHandler": {
106+
"@type": "DefaultRequestHandler"
107+
}
104108
}
105109
}
106110
},

packages/uma/src/index.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,17 @@ export * from './views/Contract';
5959
export * from './views/ResourceDescription';
6060
export * from './views/ScopeDescription';
6161

62-
/* Replace the following with CSS types */
63-
6462
// HTTP
6563
export * from './util/http/identifier/BaseTargetExtractor';
6664
export * from './util/http/models/HttpHandler';
6765
export * from './util/http/models/HttpHandlerRoute';
6866
export * from './util/http/server/ErrorHandler';
67+
export * from './util/http/server/JsonFormHttpHandler';
6968
export * from './util/http/server/NodeHttpRequestResponseHandler';
7069
export * from './util/http/server/RoutedHttpRequestHandler';
70+
71+
// Util
72+
export * from './util/ConvertUtil';
73+
export * from './util/HttpMessageSignatures';
74+
export * from './util/Result';
75+
export * from './util/ReType';

packages/uma/src/routes/Config.ts

Lines changed: 10 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,17 @@ export enum ResponseType {
88
Token = 'token',
99
Code = 'code',
1010
IDToken = 'id_token'
11-
};
11+
}
1212
// eslint-enable
1313

1414
export type OAuthConfiguration = {
15-
issuer: string,
16-
jwks_uri?: string,
17-
token_endpoint?: string,
18-
grant_types_supported?: string[],
19-
dpop_signing_alg_values_supported?: string[],
20-
response_types_supported?: ResponseType[]
21-
scopes_supported?: string[]
15+
issuer: string,
16+
jwks_uri?: string,
17+
token_endpoint?: string,
18+
grant_types_supported?: string[],
19+
dpop_signing_alg_values_supported?: string[],
20+
response_types_supported?: ResponseType[]
21+
scopes_supported?: string[]
2222
}
2323

2424
export type UmaConfiguration = OAuthConfiguration & {
@@ -44,18 +44,11 @@ export class ConfigRequestHandler extends HttpHandler {
4444
super();
4545
}
4646

47-
/**
48-
* Returns the endpoint's UMA configuration
49-
*
50-
* @param {HttpHandlerContext} context - an irrelevant incoming context
51-
* @return {Observable<HttpHandlerResponse>} - the mock response
52-
*/
53-
async handle(context: HttpHandlerContext): Promise<HttpHandlerResponse> {
47+
public async handle(context: HttpHandlerContext): Promise<HttpHandlerResponse> {
5448
this.logger.info(`Received discovery request at '${context.request.url}'`);
5549

5650
return {
57-
body: JSON.stringify(this.getConfig()),
58-
headers: {'content-type': 'application/json'},
51+
body: this.getConfig(),
5952
status: 200,
6053
};
6154
}

packages/uma/src/routes/Default.ts

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,15 @@
11
import { HttpHandler, HttpHandlerContext, HttpHandlerResponse } from '../util/http/models/HttpHandler';
22

33
/**
4-
* Default route handler
4+
* Default route handler that returns a 404.
55
*/
66
export class DefaultRequestHandler extends HttpHandler {
7-
/**
8-
* Default request handler returning a 404 error
9-
* @param {HttpHandlerContext} input
10-
* @return {Observable<HttpHandlerResponse<any>>}
11-
*/
127
async handle(input: HttpHandlerContext): Promise<HttpHandlerResponse<any>> {
138
return {
14-
body: JSON.stringify({
9+
body: {
1510
'status': 404,
1611
'error': 'Not Found',
17-
}),
18-
headers: {'content-type': 'application/json'},
12+
},
1913
status: 404,
2014
};
2115
}

packages/uma/src/routes/Introspection.ts

Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,8 @@
1-
2-
import { HttpHandler, HttpHandlerContext, HttpHandlerResponse } from '../util/http/models/HttpHandler';
1+
import { BadRequestHttpError, getLoggerFor, KeyValueStorage, UnauthorizedHttpError } from '@solid/community-server';
32
import { AccessToken } from '../tokens/AccessToken';
43
import { JwtTokenFactory } from '../tokens/JwtTokenFactory';
54
import { SerializedToken } from '../tokens/TokenFactory';
6-
import {
7-
BadRequestHttpError,
8-
getLoggerFor,
9-
JwkGenerator, KeyValueStorage,
10-
UnauthorizedHttpError,
11-
UnsupportedMediaTypeHttpError
12-
} from '@solid/community-server';
5+
import { HttpHandler, HttpHandlerContext, HttpHandlerResponse } from '../util/http/models/HttpHandler';
136
import { verifyRequest } from '../util/HttpMessageSignatures';
147

158
/**
@@ -27,29 +20,13 @@ export class IntrospectionHandler extends HttpHandler {
2720
constructor(
2821
private readonly tokenStore: KeyValueStorage<string, AccessToken>,
2922
private readonly jwtTokenFactory: JwtTokenFactory,
30-
private readonly keyGen: JwkGenerator,
3123
) {
3224
super();
3325
}
3426

35-
/**
36-
* Handle incoming requests for token introspection
37-
* @param {HttpHandlerContext} param0
38-
* @return {Observable<HttpHandlerResponse<any>>}
39-
*/
4027
async handle({request}: HttpHandlerContext): Promise<HttpHandlerResponse<any>> {
4128
if (!await verifyRequest(request)) throw new UnauthorizedHttpError();
4229

43-
if (request.headers['content-type'] !== 'application/x-www-form-urlencoded') {
44-
throw new UnsupportedMediaTypeHttpError(
45-
'Only Media Type "application/x-www-form-urlencoded" is supported for this route.');
46-
}
47-
48-
if (request.headers['accept'] !== 'application/json') {
49-
throw new UnsupportedMediaTypeHttpError(
50-
'Only "application/json" can be served by this route.');
51-
}
52-
5330
if (!request.body || !(request.body instanceof Object)) {
5431
throw new BadRequestHttpError('Missing request body.');
5532
}
@@ -60,14 +37,12 @@ export class IntrospectionHandler extends HttpHandler {
6037

6138
const jwt = this.opaqueToJwt(opaqueToken);
6239
return {
63-
headers: {'content-type': 'application/json'},
6440
status: 200,
6541
body: jwt,
6642
};
6743
} catch (e) {
6844
throw new BadRequestHttpError('Invalid request body.');
6945
}
70-
7146
}
7247

7348
private async opaqueToJwt(opaque: string): Promise<SerializedToken> {

packages/uma/src/routes/Jwks.ts

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { HttpHandler, HttpHandlerContext, HttpHandlerResponse } from '../util/http/models/HttpHandler';
21
import { getLoggerFor, JwkGenerator } from '@solid/community-server';
2+
import { HttpHandler, HttpHandlerContext, HttpHandlerResponse } from '../util/http/models/HttpHandler';
33

44
/**
55
* An HttpHandler used for returning the configuration
@@ -8,32 +8,20 @@ import { getLoggerFor, JwkGenerator } from '@solid/community-server';
88
export class JwksRequestHandler extends HttpHandler {
99
protected readonly logger = getLoggerFor(this);
1010

11-
/**
12-
* Yields a new request handler for JWKS
13-
* @param {JwksKeyHolder} keyholder - the keyholder to be used for serving JWKS
14-
*/
1511
public constructor(
1612
private readonly generator: JwkGenerator
1713
) {
1814
super();
1915
}
2016

21-
/**
22-
* Returns the JSON Web KeySet for specified keyholder
23-
* @param {HttpHandlerContext} context - an irrelevant incoming context
24-
* @return {Observable<HttpHandlerResponse>} - the JWKS response
25-
*/
2617
async handle(context: HttpHandlerContext): Promise<HttpHandlerResponse> {
2718
this.logger.info(`Received JWKS request at '${context.request.url}'`);
2819

2920
const key = await this.generator.getPublicKey();
3021

3122
return {
3223
status: 200,
33-
headers: {
34-
'content-type': 'application/json'
35-
},
36-
body: JSON.stringify({ keys: [ key ] }),
24+
body: { keys: [ key ] },
3725
};
3826
}
3927
}

packages/uma/src/routes/ResourceRegistration.ts

Lines changed: 8 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ import {
44
getLoggerFor,
55
KeyValueStorage,
66
MethodNotAllowedHttpError,
7-
UnauthorizedHttpError,
8-
UnsupportedMediaTypeHttpError
7+
UnauthorizedHttpError
98
} from '@solid/community-server';
109
import { randomUUID } from 'node:crypto';
1110
import {
@@ -14,9 +13,9 @@ import {
1413
HttpHandlerRequest,
1514
HttpHandlerResponse
1615
} from '../util/http/models/HttpHandler';
17-
import { ResourceDescription } from '../views/ResourceDescription';
18-
import { reType } from '../util/ReType';
1916
import { extractRequestSigner, verifyRequest } from '../util/HttpMessageSignatures';
17+
import { reType } from '../util/ReType';
18+
import { ResourceDescription } from '../views/ResourceDescription';
2019

2120
/**
2221
* A ResourceRegistrationRequestHandler is tasked with implementing
@@ -27,20 +26,12 @@ import { extractRequestSigner, verifyRequest } from '../util/HttpMessageSignatur
2726
export class ResourceRegistrationRequestHandler extends HttpHandler {
2827
protected readonly logger = getLoggerFor(this);
2928

30-
/**
31-
* @param {RequestingPartyRegistration[]} resourceServers - Pod Servers to be registered with the UMA AS
32-
*/
3329
constructor(
3430
private readonly resourceStore: KeyValueStorage<string, ResourceDescription>,
3531
) {
3632
super();
3733
}
3834

39-
/**
40-
* Handle incoming requests for resource registration
41-
* @param {HttpHandlerContext} param0
42-
* @return {Observable<HttpHandlerResponse<PermissionRegistrationResponse>>}
43-
*/
4435
async handle({ request }: HttpHandlerContext): Promise<HttpHandlerResponse<any>> {
4536
const signer = await extractRequestSigner(request);
4637

@@ -58,11 +49,7 @@ export class ResourceRegistrationRequestHandler extends HttpHandler {
5849
}
5950

6051
private async handlePost(request: HttpHandlerRequest): Promise<HttpHandlerResponse<any>> {
61-
const { headers, body } = request;
62-
63-
if (headers['content-type'] !== 'application/json') {
64-
throw new UnsupportedMediaTypeHttpError('Only Media Type "application/json" is supported for this route.');
65-
}
52+
const { body } = request;
6653

6754
try {
6855
reType(body, ResourceDescription);
@@ -72,19 +59,16 @@ export class ResourceRegistrationRequestHandler extends HttpHandler {
7259
}
7360

7461
const resource = randomUUID();
75-
this.resourceStore.set(resource, body);
62+
await this.resourceStore.set(resource, body);
7663

7764
this.logger.info(`Registered resource ${resource}.`);
7865

7966
return ({
8067
status: 201,
81-
headers: {
82-
'content-type': 'application/json'
83-
},
84-
body: JSON.stringify({
68+
body: {
8569
_id: resource,
8670
user_access_policy_uri: 'TODO: implement policy UI',
87-
}),
71+
},
8872
})
8973
}
9074

@@ -97,9 +81,6 @@ export class ResourceRegistrationRequestHandler extends HttpHandler {
9781

9882
this.logger.info(`Deleted resource ${parameters.id}.`);
9983

100-
return ({
101-
status: 204,
102-
headers: {},
103-
});
84+
return { status: 204 };
10485
}
10586
}

0 commit comments

Comments
 (0)