feat: adding client register
Signed-off-by: benjdlambert <ben@blam.sh> Signed-off-by: benjdlambert <ben@blam.sh>
This commit is contained in:
@@ -37,6 +37,8 @@ describe('OidcRouter', () => {
|
||||
}),
|
||||
} as unknown as UserInfoDatabase;
|
||||
|
||||
const mockOidc = {};
|
||||
|
||||
const { server } = await startTestBackend({
|
||||
features: [
|
||||
createBackendPlugin({
|
||||
|
||||
@@ -15,10 +15,12 @@
|
||||
*/
|
||||
import Router from 'express-promise-router';
|
||||
import { OidcService } from './OidcService';
|
||||
import { AuthenticationError } from '@backstage/errors';
|
||||
import { AuthenticationError, isError } from '@backstage/errors';
|
||||
import { AuthService } from '@backstage/backend-plugin-api';
|
||||
import { TokenIssuer } from '../identity/types';
|
||||
import { UserInfoDatabase } from '../database/UserInfoDatabase';
|
||||
import { rest } from 'lodash';
|
||||
import { OidcDatabase } from '../database/OidcDatabase';
|
||||
|
||||
export class OidcRouter {
|
||||
private constructor(private readonly oidc: OidcService) {}
|
||||
@@ -28,6 +30,7 @@ export class OidcRouter {
|
||||
tokenIssuer: TokenIssuer;
|
||||
baseUrl: string;
|
||||
userInfo: UserInfoDatabase;
|
||||
oidc: OidcDatabase;
|
||||
}) {
|
||||
return new OidcRouter(OidcService.create(options));
|
||||
}
|
||||
@@ -68,6 +71,29 @@ export class OidcRouter {
|
||||
res.json(userInfo);
|
||||
});
|
||||
|
||||
router.get('/v1/register', async (req, res) => {
|
||||
// todo(blam): maybe add zod types for validating input
|
||||
const registrationRequest = req.body;
|
||||
if (!registrationRequest.redirect_uris?.length) {
|
||||
res.status(400).json({
|
||||
error: 'invalid_request',
|
||||
error_description: 'redirect_uris is required',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
res.json(await this.oidc.registerClient(registrationRequest));
|
||||
} catch (e) {
|
||||
res.status(500).json({
|
||||
error: 'server_error',
|
||||
error_description: `Failed to register client: ${
|
||||
isError(e) ? e.message : 'Unknown error'
|
||||
}`,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
return router;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ import { TokenIssuer } from '../identity/types';
|
||||
import { UserInfoDatabase } from '../database/UserInfoDatabase';
|
||||
import { InputError } from '@backstage/errors';
|
||||
import { decodeJwt } from 'jose';
|
||||
import crypto from 'crypto';
|
||||
import { OidcDatabase } from '../database/OidcDatabase';
|
||||
|
||||
export class OidcService {
|
||||
private constructor(
|
||||
@@ -25,6 +27,7 @@ export class OidcService {
|
||||
private readonly tokenIssuer: TokenIssuer,
|
||||
private readonly baseUrl: string,
|
||||
private readonly userInfo: UserInfoDatabase,
|
||||
private readonly oidc: OidcDatabase,
|
||||
) {}
|
||||
|
||||
static create(options: {
|
||||
@@ -32,12 +35,14 @@ export class OidcService {
|
||||
tokenIssuer: TokenIssuer;
|
||||
baseUrl: string;
|
||||
userInfo: UserInfoDatabase;
|
||||
oidc: OidcDatabase;
|
||||
}) {
|
||||
return new OidcService(
|
||||
options.auth,
|
||||
options.tokenIssuer,
|
||||
options.baseUrl,
|
||||
options.userInfo,
|
||||
options.oidc,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -65,6 +70,8 @@ export class OidcService {
|
||||
token_endpoint_auth_methods_supported: [],
|
||||
claims_supported: ['sub', 'ent'],
|
||||
grant_types_supported: [],
|
||||
authorization_endpoint: `${this.baseUrl}/v1/authorize`,
|
||||
registration_endpoint: `${this.baseUrl}/v1/register`,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -89,4 +96,25 @@ export class OidcService {
|
||||
}
|
||||
return await this.userInfo.getUserInfo(userEntityRef);
|
||||
}
|
||||
|
||||
public async registerClient(opts: {
|
||||
responseTypes?: string[];
|
||||
grantTypes?: string[];
|
||||
clientName: string;
|
||||
redirectUris?: string[];
|
||||
scope?: string;
|
||||
}) {
|
||||
const generatedClientId = crypto.randomUUID();
|
||||
const generatedClientSecret = crypto.randomUUID();
|
||||
|
||||
return await this.oidc.createClient({
|
||||
clientId: generatedClientId,
|
||||
clientName: opts.clientName,
|
||||
clientSecret: generatedClientSecret,
|
||||
redirectUris: opts.redirectUris ?? [],
|
||||
responseTypes: opts.responseTypes ?? ['code'],
|
||||
grantTypes: opts.grantTypes ?? ['authorization_code'],
|
||||
scope: opts.scope,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user