chore: fixing issue with multi signin providers

Co-authored-by: Johan Haals <johan.haals@gmail.com>
Co-authored-by: Fredrik Adelöw <freben@gmail.com>
Signed-off-by: blam <ben@blam.sh>
This commit is contained in:
blam
2021-12-01 14:13:07 +01:00
parent 64c3fc492e
commit 29d0b45c6a
10 changed files with 200 additions and 27 deletions
@@ -233,7 +233,7 @@ export class OAuthAdapter implements AuthProviderRouteHandlers {
return;
}
if (!(identity.token || identity.id)) {
if (!identity.token) {
identity.token = await this.options.tokenIssuer.issueToken({
claims: { sub: identity.id },
});
@@ -0,0 +1,39 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { BackstageIdentityResponse } from './types';
function parseJwtPayload(token: string) {
const [_header, payload, _signature] = token.split('.');
return JSON.parse(Buffer.from(payload, 'base64').toString());
}
/**
* Parses token and decorates the BackstageIdentityResponse with identity information sourced from the token
*/
export function decorateWithIdentity(
signInResolverResponse: Omit<BackstageIdentityResponse, 'identity'>,
): BackstageIdentityResponse {
const { sub, ent } = parseJwtPayload(signInResolverResponse.token);
return {
...signInResolverResponse,
identity: {
type: 'user',
userEntityRef: sub,
ownershipEntityRefs: ent ?? [sub],
},
};
}
@@ -41,7 +41,12 @@ describe('GithubAuthProvider', () => {
const tokenIssuer: TokenIssuer = {
listPublicKeys: jest.fn(),
async issueToken(params) {
return `token-for-${params.claims.sub}`;
const tokenContents = {
sub: params.claims.sub,
ent: params.claims.ent ?? [],
};
return `eyblob.${btoa(JSON.stringify(tokenContents))}.eyblob`;
},
};
const catalogIdentityClient = {
@@ -93,7 +98,13 @@ describe('GithubAuthProvider', () => {
const expected = {
backstageIdentity: {
id: 'jimmymarkum',
token: 'token-for-jimmymarkum',
token:
'eyblob.eyJzdWIiOiJqaW1teW1hcmt1bSIsImVudCI6WyJ1c2VyOmRlZmF1bHQvamltbXltYXJrdW0iXX0=.eyblob',
identity: {
ownershipEntityRefs: ['user:default/jimmymarkum'],
type: 'user',
userEntityRef: 'jimmymarkum',
},
},
providerInfo: {
accessToken: '19xasczxcm9n7gacn9jdgm19me',
@@ -138,7 +149,13 @@ describe('GithubAuthProvider', () => {
const expected = {
backstageIdentity: {
id: 'jimmymarkum',
token: 'token-for-jimmymarkum',
token:
'eyblob.eyJzdWIiOiJqaW1teW1hcmt1bSIsImVudCI6WyJ1c2VyOmRlZmF1bHQvamltbXltYXJrdW0iXX0=.eyblob',
identity: {
type: 'user',
ownershipEntityRefs: ['user:default/jimmymarkum'],
userEntityRef: 'jimmymarkum',
},
},
providerInfo: {
accessToken: '19xasczxcm9n7gacn9jdgm19me',
@@ -181,7 +198,13 @@ describe('GithubAuthProvider', () => {
const expected = {
backstageIdentity: {
id: 'jimmymarkum',
token: 'token-for-jimmymarkum',
token:
'eyblob.eyJzdWIiOiJqaW1teW1hcmt1bSIsImVudCI6WyJ1c2VyOmRlZmF1bHQvamltbXltYXJrdW0iXX0=.eyblob',
identity: {
type: 'user',
ownershipEntityRefs: ['user:default/jimmymarkum'],
userEntityRef: 'jimmymarkum',
},
},
providerInfo: {
accessToken: '19xasczxcm9n7gacn9jdgm19me',
@@ -224,7 +247,13 @@ describe('GithubAuthProvider', () => {
const expected = {
backstageIdentity: {
id: 'daveboyle',
token: 'token-for-daveboyle',
token:
'eyblob.eyJzdWIiOiJkYXZlYm95bGUiLCJlbnQiOlsidXNlcjpkZWZhdWx0L2RhdmVib3lsZSJdfQ==.eyblob',
identity: {
type: 'user',
ownershipEntityRefs: ['user:default/daveboyle'],
userEntityRef: 'daveboyle',
},
},
providerInfo: {
accessToken:
@@ -268,7 +297,13 @@ describe('GithubAuthProvider', () => {
response: {
backstageIdentity: {
id: 'ipd12039',
token: 'token-for-ipd12039',
token:
'eyblob.eyJzdWIiOiJpcGQxMjAzOSIsImVudCI6WyJ1c2VyOmRlZmF1bHQvaXBkMTIwMzkiXX0=.eyblob',
identity: {
type: 'user',
ownershipEntityRefs: ['user:default/ipd12039'],
userEntityRef: 'ipd12039',
},
},
providerInfo: {
accessToken: 'a.b.c',
@@ -321,7 +356,13 @@ describe('GithubAuthProvider', () => {
expect(response).toEqual({
backstageIdentity: {
id: 'mockuser',
token: 'token-for-mockuser',
token:
'eyblob.eyJzdWIiOiJtb2NrdXNlciIsImVudCI6WyJ1c2VyOmRlZmF1bHQvbW9ja3VzZXIiXX0=.eyblob',
identity: {
type: 'user',
ownershipEntityRefs: ['user:default/mockuser'],
userEntityRef: 'mockuser',
},
},
profile: {
displayName: 'Mocked User',
@@ -32,6 +32,7 @@ import {
AuthHandler,
SignInResolver,
StateEncoder,
BackstageIdentityResponse,
} from '../types';
import {
OAuthAdapter,
@@ -167,7 +168,26 @@ export class GithubAuthProvider implements OAuthHandlers {
};
if (this.signInResolver) {
response.backstageIdentity = await this.signInResolver(
const decorateWithIdentity = (
signInResolverResponse: Omit<BackstageIdentityResponse, 'identity'>,
): BackstageIdentityResponse => {
function parseJwtPayload(token: string) {
const [_header, payload, _signature] = token.split('.');
return JSON.parse(Buffer.from(payload, 'base64').toString());
}
const { sub, ent } = parseJwtPayload(signInResolverResponse.token);
return {
...signInResolverResponse,
identity: {
type: 'user',
userEntityRef: sub,
ownershipEntityRefs: ent ?? [sub],
},
};
// parse token
// build identity
};
const signInResolverResult = await this.signInResolver(
{
result,
profile,
@@ -178,6 +198,8 @@ export class GithubAuthProvider implements OAuthHandlers {
logger: this.logger,
},
);
response.backstageIdentity = decorateWithIdentity(signInResolverResult);
}
return response;
@@ -159,7 +159,7 @@ export class GoogleAuthProvider implements OAuthHandlers {
};
if (this.signInResolver) {
response.backstageIdentity = await this.signInResolver(
const signInResolverResult = await this.signInResolver(
{
result,
profile,
@@ -170,6 +170,8 @@ export class GoogleAuthProvider implements OAuthHandlers {
logger: this.logger,
},
);
console.log(signInResolverResult);
}
return response;
+2 -2
View File
@@ -196,7 +196,7 @@ export type BackstageIdentityResponse = {
/**
* A plaintext description of the identity that is encapsulated within the token.
*/
identity?: BackstageUserIdentity;
identity: BackstageUserIdentity;
};
/**
@@ -242,7 +242,7 @@ export type SignInResolver<AuthResult> = (
catalogIdentityClient: CatalogIdentityClient;
logger: Logger;
},
) => Promise<BackstageIdentityResponse>;
) => Promise<Omit<BackstageIdentityResponse, 'identity'>>;
export type AuthHandlerResult = { profile: ProfileInfo };