fix some review comments
Signed-off-by: Brian Fletcher <brian@roadie.io>
This commit is contained in:
@@ -26,6 +26,7 @@ import { setupServer } from 'msw/node';
|
||||
import { v4 as uuid } from 'uuid';
|
||||
|
||||
import { DefaultIdentityClient } from './DefaultIdentityClient';
|
||||
import { IdentityApiGetIdentityRequest } from './types';
|
||||
|
||||
interface AnyJWK extends Record<string, string> {
|
||||
use: 'sig';
|
||||
@@ -366,4 +367,51 @@ describe('DefaultIdentityClient', () => {
|
||||
dateSpy.mockClear();
|
||||
});
|
||||
});
|
||||
|
||||
describe('getIdentity', () => {
|
||||
beforeEach(() => {
|
||||
server.use(
|
||||
rest.get(
|
||||
`${mockBaseUrl}/.well-known/jwks.json`,
|
||||
async (_, res, ctx) => {
|
||||
const keys = await factory.listPublicKeys();
|
||||
return res(ctx.json(keys));
|
||||
},
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
it('returns the identity', async () => {
|
||||
const token = await factory.issueToken({
|
||||
claims: { sub: 'foo', ent: ['entity1', 'entity2'] },
|
||||
});
|
||||
const response = await client.getIdentity({
|
||||
request: { headers: { authorization: `Bearer ${token}` } },
|
||||
} as IdentityApiGetIdentityRequest);
|
||||
expect(response).toEqual({
|
||||
token: token,
|
||||
identity: {
|
||||
type: 'user',
|
||||
userEntityRef: 'foo',
|
||||
ownershipEntityRefs: ['entity1', 'entity2'],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('given a corrupt the identity', async () => {
|
||||
await expect(
|
||||
client.getIdentity({
|
||||
request: { headers: { authorization: `Bearer bad-token` } },
|
||||
} as IdentityApiGetIdentityRequest),
|
||||
).rejects.toThrow('Invalid JWT');
|
||||
});
|
||||
|
||||
it('given no authorization header', async () => {
|
||||
expect(
|
||||
await client.getIdentity({
|
||||
request: { headers: {} },
|
||||
} as IdentityApiGetIdentityRequest),
|
||||
).toEqual(undefined);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -24,9 +24,11 @@ import {
|
||||
jwtVerify,
|
||||
} from 'jose';
|
||||
import { GetKeyFunction } from 'jose/dist/types/types';
|
||||
import { Request } from 'express';
|
||||
|
||||
import { BackstageIdentityResponse } from './types';
|
||||
import {
|
||||
BackstageIdentityResponse,
|
||||
IdentityApiGetIdentityRequest,
|
||||
} from './types';
|
||||
import { getBearerTokenFromAuthorizationHeader, IdentityApi } from '.';
|
||||
|
||||
const CLOCK_MARGIN_S = 10;
|
||||
@@ -75,14 +77,13 @@ export class DefaultIdentityClient implements IdentityApi {
|
||||
: ['ES256'];
|
||||
}
|
||||
|
||||
async getIdentity(req: Request) {
|
||||
try {
|
||||
return await this.authenticate(
|
||||
getBearerTokenFromAuthorizationHeader(req.headers.authorization),
|
||||
);
|
||||
} catch (e) {
|
||||
async getIdentity({ request }: IdentityApiGetIdentityRequest) {
|
||||
if (!request.headers.authorization) {
|
||||
return undefined;
|
||||
}
|
||||
return await this.authenticate(
|
||||
getBearerTokenFromAuthorizationHeader(request.headers.authorization),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -13,8 +13,10 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { BackstageIdentityResponse } from './types';
|
||||
import { Request } from 'express';
|
||||
import {
|
||||
BackstageIdentityResponse,
|
||||
IdentityApiGetIdentityRequest,
|
||||
} from './types';
|
||||
|
||||
/**
|
||||
* An identity client api to authenticate Backstage
|
||||
@@ -30,6 +32,6 @@ export interface IdentityApi {
|
||||
* The method throws an error if verification fails.
|
||||
*/
|
||||
getIdentity(
|
||||
req: Request<any>,
|
||||
options: IdentityApiGetIdentityRequest,
|
||||
): Promise<BackstageIdentityResponse | undefined>;
|
||||
}
|
||||
|
||||
@@ -29,4 +29,5 @@ export type {
|
||||
BackstageIdentityResponse,
|
||||
BackstageSignInResult,
|
||||
BackstageUserIdentity,
|
||||
IdentityApiGetIdentityRequest,
|
||||
} from './types';
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Request } from 'express';
|
||||
|
||||
/**
|
||||
* A representation of a successful Backstage sign-in.
|
||||
*
|
||||
@@ -29,6 +31,15 @@ export interface BackstageSignInResult {
|
||||
token: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Options to request the identity from a Backstage backend request
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
export type IdentityApiGetIdentityRequest = {
|
||||
request: Request<unknown>;
|
||||
};
|
||||
|
||||
/**
|
||||
* Response object containing the {@link BackstageUserIdentity} and the token
|
||||
* from the authentication provider.
|
||||
|
||||
Reference in New Issue
Block a user