@backstage/plugin-auth-backend 0.13.0-next.1 → 0.13.1-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +295 -0
- package/config.d.ts +3 -0
- package/dist/index.cjs.js +830 -1143
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +637 -63
- package/package.json +12 -12
package/dist/index.cjs.js
CHANGED
|
@@ -11,7 +11,6 @@ var pickBy = require('lodash/pickBy');
|
|
|
11
11
|
var crypto = require('crypto');
|
|
12
12
|
var url = require('url');
|
|
13
13
|
var jwtDecoder = require('jwt-decode');
|
|
14
|
-
var catalogModel = require('@backstage/catalog-model');
|
|
15
14
|
var fetch = require('node-fetch');
|
|
16
15
|
var NodeCache = require('node-cache');
|
|
17
16
|
var jose = require('jose');
|
|
@@ -29,6 +28,7 @@ var googleAuthLibrary = require('google-auth-library');
|
|
|
29
28
|
var catalogClient = require('@backstage/catalog-client');
|
|
30
29
|
var uuid = require('uuid');
|
|
31
30
|
var luxon = require('luxon');
|
|
31
|
+
var catalogModel = require('@backstage/catalog-model');
|
|
32
32
|
var backendCommon = require('@backstage/backend-common');
|
|
33
33
|
var firestore = require('@google-cloud/firestore');
|
|
34
34
|
var lodash = require('lodash');
|
|
@@ -542,75 +542,12 @@ const executeFetchUserProfileStrategy = async (providerStrategy, accessToken) =>
|
|
|
542
542
|
});
|
|
543
543
|
};
|
|
544
544
|
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
const filter = {
|
|
552
|
-
kind: "user"
|
|
553
|
-
};
|
|
554
|
-
for (const [key, value] of Object.entries(query.annotations)) {
|
|
555
|
-
filter[`metadata.annotations.${key}`] = value;
|
|
556
|
-
}
|
|
557
|
-
const { token } = await this.tokenManager.getToken();
|
|
558
|
-
const { items } = await this.catalogApi.getEntities({ filter }, { token });
|
|
559
|
-
if (items.length !== 1) {
|
|
560
|
-
if (items.length > 1) {
|
|
561
|
-
throw new errors.ConflictError("User lookup resulted in multiple matches");
|
|
562
|
-
} else {
|
|
563
|
-
throw new errors.NotFoundError("User not found");
|
|
564
|
-
}
|
|
565
|
-
}
|
|
566
|
-
return items[0];
|
|
567
|
-
}
|
|
568
|
-
async resolveCatalogMembership(query) {
|
|
569
|
-
const { entityRefs, logger } = query;
|
|
570
|
-
const resolvedEntityRefs = entityRefs.map((ref) => {
|
|
571
|
-
try {
|
|
572
|
-
const parsedRef = catalogModel.parseEntityRef(ref.toLocaleLowerCase("en-US"), {
|
|
573
|
-
defaultKind: "user",
|
|
574
|
-
defaultNamespace: "default"
|
|
575
|
-
});
|
|
576
|
-
return parsedRef;
|
|
577
|
-
} catch {
|
|
578
|
-
logger == null ? void 0 : logger.warn(`Failed to parse entityRef from ${ref}, ignoring`);
|
|
579
|
-
return null;
|
|
580
|
-
}
|
|
581
|
-
}).filter((ref) => ref !== null);
|
|
582
|
-
const filter = resolvedEntityRefs.map((ref) => ({
|
|
583
|
-
kind: ref.kind,
|
|
584
|
-
"metadata.namespace": ref.namespace,
|
|
585
|
-
"metadata.name": ref.name
|
|
586
|
-
}));
|
|
587
|
-
const { token } = await this.tokenManager.getToken();
|
|
588
|
-
const entities = await this.catalogApi.getEntities({ filter }, { token }).then((r) => r.items);
|
|
589
|
-
if (entityRefs.length !== entities.length) {
|
|
590
|
-
const foundEntityNames = entities.map(catalogModel.stringifyEntityRef);
|
|
591
|
-
const missingEntityNames = resolvedEntityRefs.map(catalogModel.stringifyEntityRef).filter((s) => !foundEntityNames.includes(s));
|
|
592
|
-
logger == null ? void 0 : logger.debug(`Entities not found for refs ${missingEntityNames.join()}`);
|
|
593
|
-
}
|
|
594
|
-
const memberOf = entities.flatMap((e) => {
|
|
595
|
-
var _a, _b;
|
|
596
|
-
return (_b = (_a = e.relations) == null ? void 0 : _a.filter((r) => r.type === catalogModel.RELATION_MEMBER_OF).map((r) => r.targetRef)) != null ? _b : [];
|
|
597
|
-
});
|
|
598
|
-
const newEntityRefs = [
|
|
599
|
-
...new Set(resolvedEntityRefs.map(catalogModel.stringifyEntityRef).concat(memberOf))
|
|
600
|
-
];
|
|
601
|
-
logger == null ? void 0 : logger.debug(`Found catalog membership: ${newEntityRefs.join()}`);
|
|
602
|
-
return newEntityRefs;
|
|
603
|
-
}
|
|
604
|
-
}
|
|
605
|
-
|
|
606
|
-
function getEntityClaims(entity) {
|
|
607
|
-
var _a, _b;
|
|
608
|
-
const userRef = catalogModel.stringifyEntityRef(entity);
|
|
609
|
-
const membershipRefs = (_b = (_a = entity.relations) == null ? void 0 : _a.filter((r) => r.type === catalogModel.RELATION_MEMBER_OF && r.targetRef.startsWith("group:")).map((r) => r.targetRef)) != null ? _b : [];
|
|
610
|
-
return {
|
|
611
|
-
sub: userRef,
|
|
612
|
-
ent: [userRef, ...membershipRefs]
|
|
613
|
-
};
|
|
545
|
+
function createAuthProviderIntegration(config) {
|
|
546
|
+
var _a;
|
|
547
|
+
return Object.freeze({
|
|
548
|
+
...config,
|
|
549
|
+
resolvers: Object.freeze((_a = config.resolvers) != null ? _a : {})
|
|
550
|
+
});
|
|
614
551
|
}
|
|
615
552
|
|
|
616
553
|
const atlassianDefaultAuthHandler = async ({
|
|
@@ -621,9 +558,7 @@ const atlassianDefaultAuthHandler = async ({
|
|
|
621
558
|
});
|
|
622
559
|
class AtlassianAuthProvider {
|
|
623
560
|
constructor(options) {
|
|
624
|
-
this.
|
|
625
|
-
this.logger = options.logger;
|
|
626
|
-
this.tokenIssuer = options.tokenIssuer;
|
|
561
|
+
this.resolverContext = options.resolverContext;
|
|
627
562
|
this.authHandler = options.authHandler;
|
|
628
563
|
this.signInResolver = options.signInResolver;
|
|
629
564
|
this._strategy = new AtlassianStrategy({
|
|
@@ -653,12 +588,7 @@ class AtlassianAuthProvider {
|
|
|
653
588
|
};
|
|
654
589
|
}
|
|
655
590
|
async handleResult(result) {
|
|
656
|
-
const
|
|
657
|
-
logger: this.logger,
|
|
658
|
-
catalogIdentityClient: this.catalogIdentityClient,
|
|
659
|
-
tokenIssuer: this.tokenIssuer
|
|
660
|
-
};
|
|
661
|
-
const { profile } = await this.authHandler(result, context);
|
|
591
|
+
const { profile } = await this.authHandler(result, this.resolverContext);
|
|
662
592
|
const response = {
|
|
663
593
|
providerInfo: {
|
|
664
594
|
idToken: result.params.id_token,
|
|
@@ -672,7 +602,7 @@ class AtlassianAuthProvider {
|
|
|
672
602
|
response.backstageIdentity = await this.signInResolver({
|
|
673
603
|
result,
|
|
674
604
|
profile
|
|
675
|
-
},
|
|
605
|
+
}, this.resolverContext);
|
|
676
606
|
}
|
|
677
607
|
return response;
|
|
678
608
|
}
|
|
@@ -689,45 +619,33 @@ class AtlassianAuthProvider {
|
|
|
689
619
|
};
|
|
690
620
|
}
|
|
691
621
|
}
|
|
692
|
-
const
|
|
693
|
-
|
|
694
|
-
providerId,
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
clientSecret,
|
|
716
|
-
scopes,
|
|
717
|
-
callbackUrl,
|
|
718
|
-
authHandler,
|
|
719
|
-
signInResolver: (_b = options == null ? void 0 : options.signIn) == null ? void 0 : _b.resolver,
|
|
720
|
-
catalogIdentityClient,
|
|
721
|
-
logger,
|
|
722
|
-
tokenIssuer
|
|
723
|
-
});
|
|
724
|
-
return OAuthAdapter.fromConfig(globalConfig, provider, {
|
|
725
|
-
providerId,
|
|
726
|
-
tokenIssuer,
|
|
727
|
-
callbackUrl
|
|
622
|
+
const atlassian = createAuthProviderIntegration({
|
|
623
|
+
create(options) {
|
|
624
|
+
return ({ providerId, globalConfig, config, resolverContext }) => OAuthEnvironmentHandler.mapConfig(config, (envConfig) => {
|
|
625
|
+
var _a, _b;
|
|
626
|
+
const clientId = envConfig.getString("clientId");
|
|
627
|
+
const clientSecret = envConfig.getString("clientSecret");
|
|
628
|
+
const scopes = envConfig.getString("scopes");
|
|
629
|
+
const customCallbackUrl = envConfig.getOptionalString("callbackUrl");
|
|
630
|
+
const callbackUrl = customCallbackUrl || `${globalConfig.baseUrl}/${providerId}/handler/frame`;
|
|
631
|
+
const authHandler = (_a = options == null ? void 0 : options.authHandler) != null ? _a : atlassianDefaultAuthHandler;
|
|
632
|
+
const provider = new AtlassianAuthProvider({
|
|
633
|
+
clientId,
|
|
634
|
+
clientSecret,
|
|
635
|
+
scopes,
|
|
636
|
+
callbackUrl,
|
|
637
|
+
authHandler,
|
|
638
|
+
signInResolver: (_b = options == null ? void 0 : options.signIn) == null ? void 0 : _b.resolver,
|
|
639
|
+
resolverContext
|
|
640
|
+
});
|
|
641
|
+
return OAuthAdapter.fromConfig(globalConfig, provider, {
|
|
642
|
+
providerId,
|
|
643
|
+
callbackUrl
|
|
644
|
+
});
|
|
728
645
|
});
|
|
729
|
-
}
|
|
730
|
-
};
|
|
646
|
+
}
|
|
647
|
+
});
|
|
648
|
+
const createAtlassianProvider = atlassian.create;
|
|
731
649
|
|
|
732
650
|
class Auth0Strategy extends OAuth2Strategy__default["default"] {
|
|
733
651
|
constructor(options, verify) {
|
|
@@ -746,9 +664,7 @@ class Auth0AuthProvider {
|
|
|
746
664
|
constructor(options) {
|
|
747
665
|
this.signInResolver = options.signInResolver;
|
|
748
666
|
this.authHandler = options.authHandler;
|
|
749
|
-
this.
|
|
750
|
-
this.catalogIdentityClient = options.catalogIdentityClient;
|
|
751
|
-
this.logger = options.logger;
|
|
667
|
+
this.resolverContext = options.resolverContext;
|
|
752
668
|
this._strategy = new Auth0Strategy({
|
|
753
669
|
clientID: options.clientId,
|
|
754
670
|
clientSecret: options.clientSecret,
|
|
@@ -794,12 +710,7 @@ class Auth0AuthProvider {
|
|
|
794
710
|
};
|
|
795
711
|
}
|
|
796
712
|
async handleResult(result) {
|
|
797
|
-
const
|
|
798
|
-
logger: this.logger,
|
|
799
|
-
catalogIdentityClient: this.catalogIdentityClient,
|
|
800
|
-
tokenIssuer: this.tokenIssuer
|
|
801
|
-
};
|
|
802
|
-
const { profile } = await this.authHandler(result, context);
|
|
713
|
+
const { profile } = await this.authHandler(result, this.resolverContext);
|
|
803
714
|
const response = {
|
|
804
715
|
providerInfo: {
|
|
805
716
|
idToken: result.params.id_token,
|
|
@@ -813,78 +724,52 @@ class Auth0AuthProvider {
|
|
|
813
724
|
response.backstageIdentity = await this.signInResolver({
|
|
814
725
|
result,
|
|
815
726
|
profile
|
|
816
|
-
},
|
|
727
|
+
}, this.resolverContext);
|
|
817
728
|
}
|
|
818
729
|
return response;
|
|
819
730
|
}
|
|
820
731
|
}
|
|
821
|
-
const
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
const
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
});
|
|
849
|
-
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ fullProfile, params }) => ({
|
|
850
|
-
profile: makeProfileInfo(fullProfile, params.id_token)
|
|
851
|
-
});
|
|
852
|
-
const signInResolver = (_b = (_a = options == null ? void 0 : options.signIn) == null ? void 0 : _a.resolver) != null ? _b : defaultSignInResolver$1;
|
|
853
|
-
const provider = new Auth0AuthProvider({
|
|
854
|
-
clientId,
|
|
855
|
-
clientSecret,
|
|
856
|
-
callbackUrl,
|
|
857
|
-
domain,
|
|
858
|
-
authHandler,
|
|
859
|
-
signInResolver,
|
|
860
|
-
tokenIssuer,
|
|
861
|
-
catalogIdentityClient,
|
|
862
|
-
logger
|
|
863
|
-
});
|
|
864
|
-
return OAuthAdapter.fromConfig(globalConfig, provider, {
|
|
865
|
-
disableRefresh: true,
|
|
866
|
-
providerId,
|
|
867
|
-
tokenIssuer,
|
|
868
|
-
callbackUrl
|
|
732
|
+
const auth0 = createAuthProviderIntegration({
|
|
733
|
+
create(options) {
|
|
734
|
+
return ({ providerId, globalConfig, config, resolverContext }) => OAuthEnvironmentHandler.mapConfig(config, (envConfig) => {
|
|
735
|
+
var _a;
|
|
736
|
+
const clientId = envConfig.getString("clientId");
|
|
737
|
+
const clientSecret = envConfig.getString("clientSecret");
|
|
738
|
+
const domain = envConfig.getString("domain");
|
|
739
|
+
const customCallbackUrl = envConfig.getOptionalString("callbackUrl");
|
|
740
|
+
const callbackUrl = customCallbackUrl || `${globalConfig.baseUrl}/${providerId}/handler/frame`;
|
|
741
|
+
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ fullProfile, params }) => ({
|
|
742
|
+
profile: makeProfileInfo(fullProfile, params.id_token)
|
|
743
|
+
});
|
|
744
|
+
const signInResolver = (_a = options == null ? void 0 : options.signIn) == null ? void 0 : _a.resolver;
|
|
745
|
+
const provider = new Auth0AuthProvider({
|
|
746
|
+
clientId,
|
|
747
|
+
clientSecret,
|
|
748
|
+
callbackUrl,
|
|
749
|
+
domain,
|
|
750
|
+
authHandler,
|
|
751
|
+
signInResolver,
|
|
752
|
+
resolverContext
|
|
753
|
+
});
|
|
754
|
+
return OAuthAdapter.fromConfig(globalConfig, provider, {
|
|
755
|
+
disableRefresh: true,
|
|
756
|
+
providerId,
|
|
757
|
+
callbackUrl
|
|
758
|
+
});
|
|
869
759
|
});
|
|
870
|
-
}
|
|
871
|
-
};
|
|
760
|
+
}
|
|
761
|
+
});
|
|
762
|
+
const createAuth0Provider = auth0.create;
|
|
872
763
|
|
|
873
764
|
const ALB_JWT_HEADER = "x-amzn-oidc-data";
|
|
874
765
|
const ALB_ACCESS_TOKEN_HEADER = "x-amzn-oidc-accesstoken";
|
|
875
|
-
const getJWTHeaders = (input) => {
|
|
876
|
-
const encoded = input.split(".")[0];
|
|
877
|
-
return JSON.parse(Buffer.from(encoded, "base64").toString("utf8"));
|
|
878
|
-
};
|
|
879
766
|
class AwsAlbAuthProvider {
|
|
880
767
|
constructor(options) {
|
|
881
768
|
this.region = options.region;
|
|
882
769
|
this.issuer = options.issuer;
|
|
883
770
|
this.authHandler = options.authHandler;
|
|
884
771
|
this.signInResolver = options.signInResolver;
|
|
885
|
-
this.
|
|
886
|
-
this.catalogIdentityClient = options.catalogIdentityClient;
|
|
887
|
-
this.logger = options.logger;
|
|
772
|
+
this.resolverContext = options.resolverContext;
|
|
888
773
|
this.keyCache = new NodeCache__default["default"]({ stdTTL: 3600 });
|
|
889
774
|
}
|
|
890
775
|
frameHandler() {
|
|
@@ -896,9 +781,7 @@ class AwsAlbAuthProvider {
|
|
|
896
781
|
const response = await this.handleResult(result);
|
|
897
782
|
res.json(response);
|
|
898
783
|
} catch (e) {
|
|
899
|
-
|
|
900
|
-
res.status(401);
|
|
901
|
-
res.end();
|
|
784
|
+
throw new errors.AuthenticationError("Exception occurred during AWS ALB token refresh", e);
|
|
902
785
|
}
|
|
903
786
|
}
|
|
904
787
|
start() {
|
|
@@ -914,9 +797,8 @@ class AwsAlbAuthProvider {
|
|
|
914
797
|
throw new errors.AuthenticationError(`Missing ALB OIDC header: ${ALB_ACCESS_TOKEN_HEADER}`);
|
|
915
798
|
}
|
|
916
799
|
try {
|
|
917
|
-
const
|
|
918
|
-
const
|
|
919
|
-
const claims = jose.JWT.verify(jwt, key);
|
|
800
|
+
const verifyResult = await jose.jwtVerify(jwt, this.getKey);
|
|
801
|
+
const claims = verifyResult.payload;
|
|
920
802
|
if (this.issuer && claims.iss !== this.issuer) {
|
|
921
803
|
throw new errors.AuthenticationError("Issuer mismatch on JWT token");
|
|
922
804
|
}
|
|
@@ -942,16 +824,11 @@ class AwsAlbAuthProvider {
|
|
|
942
824
|
}
|
|
943
825
|
}
|
|
944
826
|
async handleResult(result) {
|
|
945
|
-
const
|
|
946
|
-
tokenIssuer: this.tokenIssuer,
|
|
947
|
-
catalogIdentityClient: this.catalogIdentityClient,
|
|
948
|
-
logger: this.logger
|
|
949
|
-
};
|
|
950
|
-
const { profile } = await this.authHandler(result, context);
|
|
827
|
+
const { profile } = await this.authHandler(result, this.resolverContext);
|
|
951
828
|
const backstageIdentity = await this.signInResolver({
|
|
952
829
|
result,
|
|
953
830
|
profile
|
|
954
|
-
},
|
|
831
|
+
}, this.resolverContext);
|
|
955
832
|
return {
|
|
956
833
|
providerInfo: {
|
|
957
834
|
accessToken: result.accessToken,
|
|
@@ -961,51 +838,48 @@ class AwsAlbAuthProvider {
|
|
|
961
838
|
profile
|
|
962
839
|
};
|
|
963
840
|
}
|
|
964
|
-
async getKey(
|
|
965
|
-
|
|
841
|
+
async getKey(header) {
|
|
842
|
+
if (!header.kid) {
|
|
843
|
+
throw new errors.AuthenticationError("No key id was specified in header");
|
|
844
|
+
}
|
|
845
|
+
const optionalCacheKey = this.keyCache.get(header.kid);
|
|
966
846
|
if (optionalCacheKey) {
|
|
967
847
|
return crypto__namespace.createPublicKey(optionalCacheKey);
|
|
968
848
|
}
|
|
969
|
-
const keyText = await fetch__default["default"](`https://public-keys.auth.elb.${this.region}.amazonaws.com/${
|
|
849
|
+
const keyText = await fetch__default["default"](`https://public-keys.auth.elb.${encodeURIComponent(this.region)}.amazonaws.com/${encodeURIComponent(header.kid)}`).then((response) => response.text());
|
|
970
850
|
const keyValue = crypto__namespace.createPublicKey(keyText);
|
|
971
|
-
this.keyCache.set(
|
|
851
|
+
this.keyCache.set(header.kid, keyValue.export({ format: "pem", type: "spki" }));
|
|
972
852
|
return keyValue;
|
|
973
853
|
}
|
|
974
854
|
}
|
|
975
|
-
const
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
logger
|
|
998
|
-
});
|
|
999
|
-
};
|
|
1000
|
-
};
|
|
855
|
+
const awsAlb = createAuthProviderIntegration({
|
|
856
|
+
create(options) {
|
|
857
|
+
return ({ config, resolverContext }) => {
|
|
858
|
+
const region = config.getString("region");
|
|
859
|
+
const issuer = config.getOptionalString("iss");
|
|
860
|
+
if ((options == null ? void 0 : options.signIn.resolver) === void 0) {
|
|
861
|
+
throw new Error("SignInResolver is required to use this authentication provider");
|
|
862
|
+
}
|
|
863
|
+
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ fullProfile }) => ({
|
|
864
|
+
profile: makeProfileInfo(fullProfile)
|
|
865
|
+
});
|
|
866
|
+
return new AwsAlbAuthProvider({
|
|
867
|
+
region,
|
|
868
|
+
issuer,
|
|
869
|
+
signInResolver: options == null ? void 0 : options.signIn.resolver,
|
|
870
|
+
authHandler,
|
|
871
|
+
resolverContext
|
|
872
|
+
});
|
|
873
|
+
};
|
|
874
|
+
}
|
|
875
|
+
});
|
|
876
|
+
const createAwsAlbProvider = awsAlb.create;
|
|
1001
877
|
|
|
1002
878
|
class BitbucketAuthProvider {
|
|
1003
879
|
constructor(options) {
|
|
1004
880
|
this.signInResolver = options.signInResolver;
|
|
1005
881
|
this.authHandler = options.authHandler;
|
|
1006
|
-
this.
|
|
1007
|
-
this.catalogIdentityClient = options.catalogIdentityClient;
|
|
1008
|
-
this.logger = options.logger;
|
|
882
|
+
this.resolverContext = options.resolverContext;
|
|
1009
883
|
this._strategy = new passportBitbucketOauth2.Strategy({
|
|
1010
884
|
clientID: options.clientId,
|
|
1011
885
|
clientSecret: options.clientSecret,
|
|
@@ -1051,12 +925,7 @@ class BitbucketAuthProvider {
|
|
|
1051
925
|
}
|
|
1052
926
|
async handleResult(result) {
|
|
1053
927
|
result.fullProfile.avatarUrl = result.fullProfile._json.links.avatar.href;
|
|
1054
|
-
const
|
|
1055
|
-
logger: this.logger,
|
|
1056
|
-
catalogIdentityClient: this.catalogIdentityClient,
|
|
1057
|
-
tokenIssuer: this.tokenIssuer
|
|
1058
|
-
};
|
|
1059
|
-
const { profile } = await this.authHandler(result, context);
|
|
928
|
+
const { profile } = await this.authHandler(result, this.resolverContext);
|
|
1060
929
|
const response = {
|
|
1061
930
|
providerInfo: {
|
|
1062
931
|
idToken: result.params.id_token,
|
|
@@ -1070,79 +939,69 @@ class BitbucketAuthProvider {
|
|
|
1070
939
|
response.backstageIdentity = await this.signInResolver({
|
|
1071
940
|
result,
|
|
1072
941
|
profile
|
|
1073
|
-
},
|
|
942
|
+
}, this.resolverContext);
|
|
1074
943
|
}
|
|
1075
944
|
return response;
|
|
1076
945
|
}
|
|
1077
946
|
}
|
|
1078
|
-
const
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
947
|
+
const bitbucket = createAuthProviderIntegration({
|
|
948
|
+
create(options) {
|
|
949
|
+
return ({ providerId, globalConfig, config, resolverContext }) => OAuthEnvironmentHandler.mapConfig(config, (envConfig) => {
|
|
950
|
+
var _a;
|
|
951
|
+
const clientId = envConfig.getString("clientId");
|
|
952
|
+
const clientSecret = envConfig.getString("clientSecret");
|
|
953
|
+
const customCallbackUrl = envConfig.getOptionalString("callbackUrl");
|
|
954
|
+
const callbackUrl = customCallbackUrl || `${globalConfig.baseUrl}/${providerId}/handler/frame`;
|
|
955
|
+
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ fullProfile, params }) => ({
|
|
956
|
+
profile: makeProfileInfo(fullProfile, params.id_token)
|
|
957
|
+
});
|
|
958
|
+
const provider = new BitbucketAuthProvider({
|
|
959
|
+
clientId,
|
|
960
|
+
clientSecret,
|
|
961
|
+
callbackUrl,
|
|
962
|
+
signInResolver: (_a = options == null ? void 0 : options.signIn) == null ? void 0 : _a.resolver,
|
|
963
|
+
authHandler,
|
|
964
|
+
resolverContext
|
|
965
|
+
});
|
|
966
|
+
return OAuthAdapter.fromConfig(globalConfig, provider, {
|
|
967
|
+
disableRefresh: false,
|
|
968
|
+
providerId,
|
|
969
|
+
callbackUrl
|
|
970
|
+
});
|
|
971
|
+
});
|
|
972
|
+
},
|
|
973
|
+
resolvers: {
|
|
974
|
+
usernameMatchingUserEntityAnnotation() {
|
|
975
|
+
return async (info, ctx) => {
|
|
976
|
+
const { result } = info;
|
|
977
|
+
if (!result.fullProfile.username) {
|
|
978
|
+
throw new Error("Bitbucket profile contained no Username");
|
|
979
|
+
}
|
|
980
|
+
return ctx.signInWithCatalogUser({
|
|
981
|
+
annotations: {
|
|
982
|
+
"bitbucket.org/username": result.fullProfile.username
|
|
983
|
+
}
|
|
984
|
+
});
|
|
985
|
+
};
|
|
986
|
+
},
|
|
987
|
+
userIdMatchingUserEntityAnnotation() {
|
|
988
|
+
return async (info, ctx) => {
|
|
989
|
+
const { result } = info;
|
|
990
|
+
if (!result.fullProfile.id) {
|
|
991
|
+
throw new Error("Bitbucket profile contained no User ID");
|
|
992
|
+
}
|
|
993
|
+
return ctx.signInWithCatalogUser({
|
|
994
|
+
annotations: {
|
|
995
|
+
"bitbucket.org/user-id": result.fullProfile.id
|
|
996
|
+
}
|
|
997
|
+
});
|
|
998
|
+
};
|
|
1086
999
|
}
|
|
1087
|
-
});
|
|
1088
|
-
const claims = getEntityClaims(entity);
|
|
1089
|
-
const token = await ctx.tokenIssuer.issueToken({ claims });
|
|
1090
|
-
return { id: entity.metadata.name, entity, token };
|
|
1091
|
-
};
|
|
1092
|
-
const bitbucketUserIdSignInResolver = async (info, ctx) => {
|
|
1093
|
-
const { result } = info;
|
|
1094
|
-
if (!result.fullProfile.id) {
|
|
1095
|
-
throw new Error("Bitbucket profile contained no User ID");
|
|
1096
1000
|
}
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
});
|
|
1102
|
-
const claims = getEntityClaims(entity);
|
|
1103
|
-
const token = await ctx.tokenIssuer.issueToken({ claims });
|
|
1104
|
-
return { id: entity.metadata.name, entity, token };
|
|
1105
|
-
};
|
|
1106
|
-
const createBitbucketProvider = (options) => {
|
|
1107
|
-
return ({
|
|
1108
|
-
providerId,
|
|
1109
|
-
globalConfig,
|
|
1110
|
-
config,
|
|
1111
|
-
tokenIssuer,
|
|
1112
|
-
tokenManager,
|
|
1113
|
-
catalogApi,
|
|
1114
|
-
logger
|
|
1115
|
-
}) => OAuthEnvironmentHandler.mapConfig(config, (envConfig) => {
|
|
1116
|
-
var _a;
|
|
1117
|
-
const clientId = envConfig.getString("clientId");
|
|
1118
|
-
const clientSecret = envConfig.getString("clientSecret");
|
|
1119
|
-
const customCallbackUrl = envConfig.getOptionalString("callbackUrl");
|
|
1120
|
-
const callbackUrl = customCallbackUrl || `${globalConfig.baseUrl}/${providerId}/handler/frame`;
|
|
1121
|
-
const catalogIdentityClient = new CatalogIdentityClient({
|
|
1122
|
-
catalogApi,
|
|
1123
|
-
tokenManager
|
|
1124
|
-
});
|
|
1125
|
-
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ fullProfile, params }) => ({
|
|
1126
|
-
profile: makeProfileInfo(fullProfile, params.id_token)
|
|
1127
|
-
});
|
|
1128
|
-
const provider = new BitbucketAuthProvider({
|
|
1129
|
-
clientId,
|
|
1130
|
-
clientSecret,
|
|
1131
|
-
callbackUrl,
|
|
1132
|
-
signInResolver: (_a = options == null ? void 0 : options.signIn) == null ? void 0 : _a.resolver,
|
|
1133
|
-
authHandler,
|
|
1134
|
-
tokenIssuer,
|
|
1135
|
-
catalogIdentityClient,
|
|
1136
|
-
logger
|
|
1137
|
-
});
|
|
1138
|
-
return OAuthAdapter.fromConfig(globalConfig, provider, {
|
|
1139
|
-
disableRefresh: false,
|
|
1140
|
-
providerId,
|
|
1141
|
-
tokenIssuer,
|
|
1142
|
-
callbackUrl
|
|
1143
|
-
});
|
|
1144
|
-
});
|
|
1145
|
-
};
|
|
1001
|
+
});
|
|
1002
|
+
const createBitbucketProvider = bitbucket.create;
|
|
1003
|
+
const bitbucketUsernameSignInResolver = bitbucket.resolvers.usernameMatchingUserEntityAnnotation();
|
|
1004
|
+
const bitbucketUserIdSignInResolver = bitbucket.resolvers.userIdMatchingUserEntityAnnotation();
|
|
1146
1005
|
|
|
1147
1006
|
const ACCESS_TOKEN_PREFIX = "access-token.";
|
|
1148
1007
|
const BACKSTAGE_SESSION_EXPIRATION = 3600;
|
|
@@ -1151,9 +1010,7 @@ class GithubAuthProvider {
|
|
|
1151
1010
|
this.signInResolver = options.signInResolver;
|
|
1152
1011
|
this.authHandler = options.authHandler;
|
|
1153
1012
|
this.stateEncoder = options.stateEncoder;
|
|
1154
|
-
this.
|
|
1155
|
-
this.catalogIdentityClient = options.catalogIdentityClient;
|
|
1156
|
-
this.logger = options.logger;
|
|
1013
|
+
this.resolverContext = options.resolverContext;
|
|
1157
1014
|
this._strategy = new passportGithub2.Strategy({
|
|
1158
1015
|
clientID: options.clientId,
|
|
1159
1016
|
clientSecret: options.clientSecret,
|
|
@@ -1213,12 +1070,7 @@ class GithubAuthProvider {
|
|
|
1213
1070
|
};
|
|
1214
1071
|
}
|
|
1215
1072
|
async handleResult(result) {
|
|
1216
|
-
const
|
|
1217
|
-
logger: this.logger,
|
|
1218
|
-
catalogIdentityClient: this.catalogIdentityClient,
|
|
1219
|
-
tokenIssuer: this.tokenIssuer
|
|
1220
|
-
};
|
|
1221
|
-
const { profile } = await this.authHandler(result, context);
|
|
1073
|
+
const { profile } = await this.authHandler(result, this.resolverContext);
|
|
1222
1074
|
const expiresInStr = result.params.expires_in;
|
|
1223
1075
|
let expiresInSeconds = expiresInStr === void 0 ? void 0 : Number(expiresInStr);
|
|
1224
1076
|
let backstageIdentity = void 0;
|
|
@@ -1226,7 +1078,7 @@ class GithubAuthProvider {
|
|
|
1226
1078
|
backstageIdentity = await this.signInResolver({
|
|
1227
1079
|
result,
|
|
1228
1080
|
profile
|
|
1229
|
-
},
|
|
1081
|
+
}, this.resolverContext);
|
|
1230
1082
|
if (expiresInSeconds) {
|
|
1231
1083
|
expiresInSeconds = Math.min(expiresInSeconds, BACKSTAGE_SESSION_EXPIRATION);
|
|
1232
1084
|
} else {
|
|
@@ -1244,99 +1096,58 @@ class GithubAuthProvider {
|
|
|
1244
1096
|
};
|
|
1245
1097
|
}
|
|
1246
1098
|
}
|
|
1247
|
-
const
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
const catalogIdentityClient = new CatalogIdentityClient({
|
|
1283
|
-
catalogApi,
|
|
1284
|
-
tokenManager
|
|
1285
|
-
});
|
|
1286
|
-
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ fullProfile }) => ({
|
|
1287
|
-
profile: makeProfileInfo(fullProfile)
|
|
1288
|
-
});
|
|
1289
|
-
const signInResolverFn = (_c = (_b = options == null ? void 0 : options.signIn) == null ? void 0 : _b.resolver) != null ? _c : githubDefaultSignInResolver;
|
|
1290
|
-
const signInResolver = (info) => signInResolverFn(info, {
|
|
1291
|
-
catalogIdentityClient,
|
|
1292
|
-
tokenIssuer,
|
|
1293
|
-
logger
|
|
1294
|
-
});
|
|
1295
|
-
const stateEncoder = (_d = options == null ? void 0 : options.stateEncoder) != null ? _d : async (req) => {
|
|
1296
|
-
return { encodedState: encodeState(req.state) };
|
|
1297
|
-
};
|
|
1298
|
-
const provider = new GithubAuthProvider({
|
|
1299
|
-
clientId,
|
|
1300
|
-
clientSecret,
|
|
1301
|
-
callbackUrl,
|
|
1302
|
-
tokenUrl,
|
|
1303
|
-
userProfileUrl,
|
|
1304
|
-
authorizationUrl,
|
|
1305
|
-
signInResolver,
|
|
1306
|
-
authHandler,
|
|
1307
|
-
tokenIssuer,
|
|
1308
|
-
catalogIdentityClient,
|
|
1309
|
-
stateEncoder,
|
|
1310
|
-
logger
|
|
1311
|
-
});
|
|
1312
|
-
return OAuthAdapter.fromConfig(globalConfig, provider, {
|
|
1313
|
-
persistScopes: true,
|
|
1314
|
-
providerId,
|
|
1315
|
-
tokenIssuer,
|
|
1316
|
-
callbackUrl
|
|
1099
|
+
const github = createAuthProviderIntegration({
|
|
1100
|
+
create(options) {
|
|
1101
|
+
return ({ providerId, globalConfig, config, resolverContext }) => OAuthEnvironmentHandler.mapConfig(config, (envConfig) => {
|
|
1102
|
+
var _a, _b, _c;
|
|
1103
|
+
const clientId = envConfig.getString("clientId");
|
|
1104
|
+
const clientSecret = envConfig.getString("clientSecret");
|
|
1105
|
+
const enterpriseInstanceUrl = (_a = envConfig.getOptionalString("enterpriseInstanceUrl")) == null ? void 0 : _a.replace(/\/$/, "");
|
|
1106
|
+
const customCallbackUrl = envConfig.getOptionalString("callbackUrl");
|
|
1107
|
+
const authorizationUrl = enterpriseInstanceUrl ? `${enterpriseInstanceUrl}/login/oauth/authorize` : void 0;
|
|
1108
|
+
const tokenUrl = enterpriseInstanceUrl ? `${enterpriseInstanceUrl}/login/oauth/access_token` : void 0;
|
|
1109
|
+
const userProfileUrl = enterpriseInstanceUrl ? `${enterpriseInstanceUrl}/api/v3/user` : void 0;
|
|
1110
|
+
const callbackUrl = customCallbackUrl || `${globalConfig.baseUrl}/${providerId}/handler/frame`;
|
|
1111
|
+
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ fullProfile }) => ({
|
|
1112
|
+
profile: makeProfileInfo(fullProfile)
|
|
1113
|
+
});
|
|
1114
|
+
const stateEncoder = (_b = options == null ? void 0 : options.stateEncoder) != null ? _b : async (req) => {
|
|
1115
|
+
return { encodedState: encodeState(req.state) };
|
|
1116
|
+
};
|
|
1117
|
+
const provider = new GithubAuthProvider({
|
|
1118
|
+
clientId,
|
|
1119
|
+
clientSecret,
|
|
1120
|
+
callbackUrl,
|
|
1121
|
+
tokenUrl,
|
|
1122
|
+
userProfileUrl,
|
|
1123
|
+
authorizationUrl,
|
|
1124
|
+
signInResolver: (_c = options == null ? void 0 : options.signIn) == null ? void 0 : _c.resolver,
|
|
1125
|
+
authHandler,
|
|
1126
|
+
stateEncoder,
|
|
1127
|
+
resolverContext
|
|
1128
|
+
});
|
|
1129
|
+
return OAuthAdapter.fromConfig(globalConfig, provider, {
|
|
1130
|
+
persistScopes: true,
|
|
1131
|
+
providerId,
|
|
1132
|
+
callbackUrl
|
|
1133
|
+
});
|
|
1317
1134
|
});
|
|
1318
|
-
}
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
namespace: catalogModel.DEFAULT_NAMESPACE,
|
|
1330
|
-
name: id
|
|
1331
|
-
});
|
|
1332
|
-
const token = await ctx.tokenIssuer.issueToken({
|
|
1333
|
-
claims: {
|
|
1334
|
-
sub: entityRef,
|
|
1335
|
-
ent: [entityRef]
|
|
1135
|
+
},
|
|
1136
|
+
resolvers: {
|
|
1137
|
+
usernameMatchingUserEntityName: () => {
|
|
1138
|
+
return async (info, ctx) => {
|
|
1139
|
+
const { fullProfile } = info.result;
|
|
1140
|
+
const userId = fullProfile.username;
|
|
1141
|
+
if (!userId) {
|
|
1142
|
+
throw new Error(`GitHub user profile does not contain a username`);
|
|
1143
|
+
}
|
|
1144
|
+
return ctx.signInWithCatalogUser({ entityRef: { name: userId } });
|
|
1145
|
+
};
|
|
1336
1146
|
}
|
|
1337
|
-
}
|
|
1338
|
-
|
|
1339
|
-
|
|
1147
|
+
}
|
|
1148
|
+
});
|
|
1149
|
+
const createGithubProvider = github.create;
|
|
1150
|
+
|
|
1340
1151
|
const gitlabDefaultAuthHandler = async ({
|
|
1341
1152
|
fullProfile,
|
|
1342
1153
|
params
|
|
@@ -1345,9 +1156,7 @@ const gitlabDefaultAuthHandler = async ({
|
|
|
1345
1156
|
});
|
|
1346
1157
|
class GitlabAuthProvider {
|
|
1347
1158
|
constructor(options) {
|
|
1348
|
-
this.
|
|
1349
|
-
this.logger = options.logger;
|
|
1350
|
-
this.tokenIssuer = options.tokenIssuer;
|
|
1159
|
+
this.resolverContext = options.resolverContext;
|
|
1351
1160
|
this.authHandler = options.authHandler;
|
|
1352
1161
|
this.signInResolver = options.signInResolver;
|
|
1353
1162
|
this._strategy = new passportGitlab2.Strategy({
|
|
@@ -1387,12 +1196,7 @@ class GitlabAuthProvider {
|
|
|
1387
1196
|
};
|
|
1388
1197
|
}
|
|
1389
1198
|
async handleResult(result) {
|
|
1390
|
-
const
|
|
1391
|
-
logger: this.logger,
|
|
1392
|
-
catalogIdentityClient: this.catalogIdentityClient,
|
|
1393
|
-
tokenIssuer: this.tokenIssuer
|
|
1394
|
-
};
|
|
1395
|
-
const { profile } = await this.authHandler(result, context);
|
|
1199
|
+
const { profile } = await this.authHandler(result, this.resolverContext);
|
|
1396
1200
|
const response = {
|
|
1397
1201
|
providerInfo: {
|
|
1398
1202
|
idToken: result.params.id_token,
|
|
@@ -1406,67 +1210,69 @@ class GitlabAuthProvider {
|
|
|
1406
1210
|
response.backstageIdentity = await this.signInResolver({
|
|
1407
1211
|
result,
|
|
1408
1212
|
profile
|
|
1409
|
-
},
|
|
1213
|
+
}, this.resolverContext);
|
|
1410
1214
|
}
|
|
1411
1215
|
return response;
|
|
1412
1216
|
}
|
|
1413
1217
|
}
|
|
1414
|
-
const
|
|
1415
|
-
|
|
1416
|
-
providerId,
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
tokenIssuer,
|
|
1440
|
-
logger
|
|
1441
|
-
});
|
|
1442
|
-
const provider = new GitlabAuthProvider({
|
|
1443
|
-
clientId,
|
|
1444
|
-
clientSecret,
|
|
1445
|
-
callbackUrl,
|
|
1446
|
-
baseUrl,
|
|
1447
|
-
authHandler,
|
|
1448
|
-
signInResolver,
|
|
1449
|
-
catalogIdentityClient,
|
|
1450
|
-
logger,
|
|
1451
|
-
tokenIssuer
|
|
1452
|
-
});
|
|
1453
|
-
return OAuthAdapter.fromConfig(globalConfig, provider, {
|
|
1454
|
-
disableRefresh: false,
|
|
1455
|
-
providerId,
|
|
1456
|
-
tokenIssuer,
|
|
1457
|
-
callbackUrl
|
|
1218
|
+
const gitlab = createAuthProviderIntegration({
|
|
1219
|
+
create(options) {
|
|
1220
|
+
return ({ providerId, globalConfig, config, resolverContext }) => OAuthEnvironmentHandler.mapConfig(config, (envConfig) => {
|
|
1221
|
+
var _a, _b;
|
|
1222
|
+
const clientId = envConfig.getString("clientId");
|
|
1223
|
+
const clientSecret = envConfig.getString("clientSecret");
|
|
1224
|
+
const audience = envConfig.getOptionalString("audience");
|
|
1225
|
+
const baseUrl = audience || "https://gitlab.com";
|
|
1226
|
+
const customCallbackUrl = envConfig.getOptionalString("callbackUrl");
|
|
1227
|
+
const callbackUrl = customCallbackUrl || `${globalConfig.baseUrl}/${providerId}/handler/frame`;
|
|
1228
|
+
const authHandler = (_a = options == null ? void 0 : options.authHandler) != null ? _a : gitlabDefaultAuthHandler;
|
|
1229
|
+
const provider = new GitlabAuthProvider({
|
|
1230
|
+
clientId,
|
|
1231
|
+
clientSecret,
|
|
1232
|
+
callbackUrl,
|
|
1233
|
+
baseUrl,
|
|
1234
|
+
authHandler,
|
|
1235
|
+
signInResolver: (_b = options == null ? void 0 : options.signIn) == null ? void 0 : _b.resolver,
|
|
1236
|
+
resolverContext
|
|
1237
|
+
});
|
|
1238
|
+
return OAuthAdapter.fromConfig(globalConfig, provider, {
|
|
1239
|
+
disableRefresh: false,
|
|
1240
|
+
providerId,
|
|
1241
|
+
callbackUrl
|
|
1242
|
+
});
|
|
1458
1243
|
});
|
|
1244
|
+
}
|
|
1245
|
+
});
|
|
1246
|
+
const createGitlabProvider = gitlab.create;
|
|
1247
|
+
|
|
1248
|
+
const commonByEmailLocalPartResolver = async (info, ctx) => {
|
|
1249
|
+
const { profile } = info;
|
|
1250
|
+
if (!profile.email) {
|
|
1251
|
+
throw new Error("Login failed, user profile does not contain an email");
|
|
1252
|
+
}
|
|
1253
|
+
const [localPart] = profile.email.split("@");
|
|
1254
|
+
return ctx.signInWithCatalogUser({
|
|
1255
|
+
entityRef: { name: localPart }
|
|
1256
|
+
});
|
|
1257
|
+
};
|
|
1258
|
+
const commonByEmailResolver = async (info, ctx) => {
|
|
1259
|
+
const { profile } = info;
|
|
1260
|
+
if (!profile.email) {
|
|
1261
|
+
throw new Error("Login failed, user profile does not contain an email");
|
|
1262
|
+
}
|
|
1263
|
+
return ctx.signInWithCatalogUser({
|
|
1264
|
+
filter: {
|
|
1265
|
+
"spec.profile.email": profile.email
|
|
1266
|
+
}
|
|
1459
1267
|
});
|
|
1460
1268
|
};
|
|
1461
1269
|
|
|
1462
1270
|
class GoogleAuthProvider {
|
|
1463
1271
|
constructor(options) {
|
|
1464
|
-
this.signInResolver = options.signInResolver;
|
|
1465
1272
|
this.authHandler = options.authHandler;
|
|
1466
|
-
this.
|
|
1467
|
-
this.
|
|
1468
|
-
this.
|
|
1469
|
-
this._strategy = new passportGoogleOauth20.Strategy({
|
|
1273
|
+
this.signInResolver = options.signInResolver;
|
|
1274
|
+
this.resolverContext = options.resolverContext;
|
|
1275
|
+
this.strategy = new passportGoogleOauth20.Strategy({
|
|
1470
1276
|
clientID: options.clientId,
|
|
1471
1277
|
clientSecret: options.clientSecret,
|
|
1472
1278
|
callbackURL: options.callbackUrl,
|
|
@@ -1483,7 +1289,7 @@ class GoogleAuthProvider {
|
|
|
1483
1289
|
});
|
|
1484
1290
|
}
|
|
1485
1291
|
async start(req) {
|
|
1486
|
-
return await executeRedirectStrategy(req, this.
|
|
1292
|
+
return await executeRedirectStrategy(req, this.strategy, {
|
|
1487
1293
|
accessType: "offline",
|
|
1488
1294
|
prompt: "consent",
|
|
1489
1295
|
scope: req.scope,
|
|
@@ -1491,15 +1297,15 @@ class GoogleAuthProvider {
|
|
|
1491
1297
|
});
|
|
1492
1298
|
}
|
|
1493
1299
|
async handler(req) {
|
|
1494
|
-
const { result, privateInfo } = await executeFrameHandlerStrategy(req, this.
|
|
1300
|
+
const { result, privateInfo } = await executeFrameHandlerStrategy(req, this.strategy);
|
|
1495
1301
|
return {
|
|
1496
1302
|
response: await this.handleResult(result),
|
|
1497
1303
|
refreshToken: privateInfo.refreshToken
|
|
1498
1304
|
};
|
|
1499
1305
|
}
|
|
1500
1306
|
async refresh(req) {
|
|
1501
|
-
const { accessToken, refreshToken, params } = await executeRefreshTokenStrategy(this.
|
|
1502
|
-
const fullProfile = await executeFetchUserProfileStrategy(this.
|
|
1307
|
+
const { accessToken, refreshToken, params } = await executeRefreshTokenStrategy(this.strategy, req.refreshToken, req.scope);
|
|
1308
|
+
const fullProfile = await executeFetchUserProfileStrategy(this.strategy, accessToken);
|
|
1503
1309
|
return {
|
|
1504
1310
|
response: await this.handleResult({
|
|
1505
1311
|
fullProfile,
|
|
@@ -1510,12 +1316,7 @@ class GoogleAuthProvider {
|
|
|
1510
1316
|
};
|
|
1511
1317
|
}
|
|
1512
1318
|
async handleResult(result) {
|
|
1513
|
-
const
|
|
1514
|
-
logger: this.logger,
|
|
1515
|
-
catalogIdentityClient: this.catalogIdentityClient,
|
|
1516
|
-
tokenIssuer: this.tokenIssuer
|
|
1517
|
-
};
|
|
1518
|
-
const { profile } = await this.authHandler(result, context);
|
|
1319
|
+
const { profile } = await this.authHandler(result, this.resolverContext);
|
|
1519
1320
|
const response = {
|
|
1520
1321
|
providerInfo: {
|
|
1521
1322
|
idToken: result.params.id_token,
|
|
@@ -1529,109 +1330,64 @@ class GoogleAuthProvider {
|
|
|
1529
1330
|
response.backstageIdentity = await this.signInResolver({
|
|
1530
1331
|
result,
|
|
1531
1332
|
profile
|
|
1532
|
-
},
|
|
1333
|
+
}, this.resolverContext);
|
|
1533
1334
|
}
|
|
1534
1335
|
return response;
|
|
1535
1336
|
}
|
|
1536
1337
|
}
|
|
1537
|
-
const
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
}
|
|
1338
|
+
const google = createAuthProviderIntegration({
|
|
1339
|
+
create(options) {
|
|
1340
|
+
return ({ providerId, globalConfig, config, resolverContext }) => OAuthEnvironmentHandler.mapConfig(config, (envConfig) => {
|
|
1341
|
+
var _a;
|
|
1342
|
+
const clientId = envConfig.getString("clientId");
|
|
1343
|
+
const clientSecret = envConfig.getString("clientSecret");
|
|
1344
|
+
const customCallbackUrl = envConfig.getOptionalString("callbackUrl");
|
|
1345
|
+
const callbackUrl = customCallbackUrl || `${globalConfig.baseUrl}/${providerId}/handler/frame`;
|
|
1346
|
+
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ fullProfile, params }) => ({
|
|
1347
|
+
profile: makeProfileInfo(fullProfile, params.id_token)
|
|
1348
|
+
});
|
|
1349
|
+
const provider = new GoogleAuthProvider({
|
|
1350
|
+
clientId,
|
|
1351
|
+
clientSecret,
|
|
1352
|
+
callbackUrl,
|
|
1353
|
+
signInResolver: (_a = options == null ? void 0 : options.signIn) == null ? void 0 : _a.resolver,
|
|
1354
|
+
authHandler,
|
|
1355
|
+
resolverContext
|
|
1356
|
+
});
|
|
1357
|
+
return OAuthAdapter.fromConfig(globalConfig, provider, {
|
|
1358
|
+
disableRefresh: false,
|
|
1359
|
+
providerId,
|
|
1360
|
+
callbackUrl
|
|
1361
|
+
});
|
|
1562
1362
|
});
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1363
|
+
},
|
|
1364
|
+
resolvers: {
|
|
1365
|
+
emailLocalPartMatchingUserEntityName: () => commonByEmailLocalPartResolver,
|
|
1366
|
+
emailMatchingUserEntityProfileEmail: () => commonByEmailResolver,
|
|
1367
|
+
emailMatchingUserEntityAnnotation() {
|
|
1368
|
+
return async (info, ctx) => {
|
|
1369
|
+
const { profile } = info;
|
|
1370
|
+
if (!profile.email) {
|
|
1371
|
+
throw new Error("Google profile contained no email");
|
|
1372
|
+
}
|
|
1373
|
+
return ctx.signInWithCatalogUser({
|
|
1374
|
+
annotations: {
|
|
1375
|
+
"google.com/email": profile.email
|
|
1376
|
+
}
|
|
1377
|
+
});
|
|
1378
|
+
};
|
|
1577
1379
|
}
|
|
1578
|
-
}
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
const
|
|
1582
|
-
return ({
|
|
1583
|
-
providerId,
|
|
1584
|
-
globalConfig,
|
|
1585
|
-
config,
|
|
1586
|
-
tokenIssuer,
|
|
1587
|
-
tokenManager,
|
|
1588
|
-
catalogApi,
|
|
1589
|
-
logger
|
|
1590
|
-
}) => OAuthEnvironmentHandler.mapConfig(config, (envConfig) => {
|
|
1591
|
-
var _a, _b;
|
|
1592
|
-
const clientId = envConfig.getString("clientId");
|
|
1593
|
-
const clientSecret = envConfig.getString("clientSecret");
|
|
1594
|
-
const customCallbackUrl = envConfig.getOptionalString("callbackUrl");
|
|
1595
|
-
const callbackUrl = customCallbackUrl || `${globalConfig.baseUrl}/${providerId}/handler/frame`;
|
|
1596
|
-
const catalogIdentityClient = new CatalogIdentityClient({
|
|
1597
|
-
catalogApi,
|
|
1598
|
-
tokenManager
|
|
1599
|
-
});
|
|
1600
|
-
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ fullProfile, params }) => ({
|
|
1601
|
-
profile: makeProfileInfo(fullProfile, params.id_token)
|
|
1602
|
-
});
|
|
1603
|
-
const signInResolverFn = (_b = (_a = options == null ? void 0 : options.signIn) == null ? void 0 : _a.resolver) != null ? _b : googleDefaultSignInResolver;
|
|
1604
|
-
const signInResolver = (info) => signInResolverFn(info, {
|
|
1605
|
-
catalogIdentityClient,
|
|
1606
|
-
tokenIssuer,
|
|
1607
|
-
logger
|
|
1608
|
-
});
|
|
1609
|
-
const provider = new GoogleAuthProvider({
|
|
1610
|
-
clientId,
|
|
1611
|
-
clientSecret,
|
|
1612
|
-
callbackUrl,
|
|
1613
|
-
signInResolver,
|
|
1614
|
-
authHandler,
|
|
1615
|
-
tokenIssuer,
|
|
1616
|
-
catalogIdentityClient,
|
|
1617
|
-
logger
|
|
1618
|
-
});
|
|
1619
|
-
return OAuthAdapter.fromConfig(globalConfig, provider, {
|
|
1620
|
-
disableRefresh: false,
|
|
1621
|
-
providerId,
|
|
1622
|
-
tokenIssuer,
|
|
1623
|
-
callbackUrl
|
|
1624
|
-
});
|
|
1625
|
-
});
|
|
1626
|
-
};
|
|
1380
|
+
}
|
|
1381
|
+
});
|
|
1382
|
+
const createGoogleProvider = google.create;
|
|
1383
|
+
const googleEmailSignInResolver = google.resolvers.emailMatchingUserEntityAnnotation();
|
|
1627
1384
|
|
|
1628
1385
|
class MicrosoftAuthProvider {
|
|
1629
1386
|
constructor(options) {
|
|
1630
1387
|
this.signInResolver = options.signInResolver;
|
|
1631
1388
|
this.authHandler = options.authHandler;
|
|
1632
|
-
this.tokenIssuer = options.tokenIssuer;
|
|
1633
1389
|
this.logger = options.logger;
|
|
1634
|
-
this.
|
|
1390
|
+
this.resolverContext = options.resolverContext;
|
|
1635
1391
|
this._strategy = new passportMicrosoft.Strategy({
|
|
1636
1392
|
clientID: options.clientId,
|
|
1637
1393
|
clientSecret: options.clientSecret,
|
|
@@ -1671,12 +1427,7 @@ class MicrosoftAuthProvider {
|
|
|
1671
1427
|
async handleResult(result) {
|
|
1672
1428
|
const photo = await this.getUserPhoto(result.accessToken);
|
|
1673
1429
|
result.fullProfile.photos = photo ? [{ value: photo }] : void 0;
|
|
1674
|
-
const
|
|
1675
|
-
logger: this.logger,
|
|
1676
|
-
catalogIdentityClient: this.catalogIdentityClient,
|
|
1677
|
-
tokenIssuer: this.tokenIssuer
|
|
1678
|
-
};
|
|
1679
|
-
const { profile } = await this.authHandler(result, context);
|
|
1430
|
+
const { profile } = await this.authHandler(result, this.resolverContext);
|
|
1680
1431
|
const response = {
|
|
1681
1432
|
providerInfo: {
|
|
1682
1433
|
idToken: result.params.id_token,
|
|
@@ -1690,118 +1441,83 @@ class MicrosoftAuthProvider {
|
|
|
1690
1441
|
response.backstageIdentity = await this.signInResolver({
|
|
1691
1442
|
result,
|
|
1692
1443
|
profile
|
|
1693
|
-
},
|
|
1444
|
+
}, this.resolverContext);
|
|
1694
1445
|
}
|
|
1695
1446
|
return response;
|
|
1696
1447
|
}
|
|
1697
|
-
getUserPhoto(accessToken) {
|
|
1698
|
-
|
|
1699
|
-
fetch__default["default"]("https://graph.microsoft.com/v1.0/me/photos/48x48/$value", {
|
|
1448
|
+
async getUserPhoto(accessToken) {
|
|
1449
|
+
try {
|
|
1450
|
+
const res = await fetch__default["default"]("https://graph.microsoft.com/v1.0/me/photos/48x48/$value", {
|
|
1700
1451
|
headers: {
|
|
1701
1452
|
Authorization: `Bearer ${accessToken}`
|
|
1702
1453
|
}
|
|
1703
|
-
}).then((response) => response.arrayBuffer()).then((arrayBuffer) => {
|
|
1704
|
-
const imageUrl = `data:image/jpeg;base64,${Buffer.from(arrayBuffer).toString("base64")}`;
|
|
1705
|
-
resolve(imageUrl);
|
|
1706
|
-
}).catch((error) => {
|
|
1707
|
-
this.logger.warn(`Could not retrieve user profile photo from Microsoft Graph API: ${error}`);
|
|
1708
|
-
resolve(void 0);
|
|
1709
1454
|
});
|
|
1710
|
-
|
|
1455
|
+
const data = await res.buffer();
|
|
1456
|
+
return `data:image/jpeg;base64,${data.toString("base64")}`;
|
|
1457
|
+
} catch (error) {
|
|
1458
|
+
this.logger.warn(`Could not retrieve user profile photo from Microsoft Graph API: ${error}`);
|
|
1459
|
+
return void 0;
|
|
1460
|
+
}
|
|
1711
1461
|
}
|
|
1712
1462
|
}
|
|
1713
|
-
const
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1463
|
+
const microsoft = createAuthProviderIntegration({
|
|
1464
|
+
create(options) {
|
|
1465
|
+
return ({ providerId, globalConfig, config, logger, resolverContext }) => OAuthEnvironmentHandler.mapConfig(config, (envConfig) => {
|
|
1466
|
+
var _a;
|
|
1467
|
+
const clientId = envConfig.getString("clientId");
|
|
1468
|
+
const clientSecret = envConfig.getString("clientSecret");
|
|
1469
|
+
const tenantId = envConfig.getString("tenantId");
|
|
1470
|
+
const customCallbackUrl = envConfig.getOptionalString("callbackUrl");
|
|
1471
|
+
const callbackUrl = customCallbackUrl || `${globalConfig.baseUrl}/${providerId}/handler/frame`;
|
|
1472
|
+
const authorizationUrl = `https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/authorize`;
|
|
1473
|
+
const tokenUrl = `https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/token`;
|
|
1474
|
+
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ fullProfile, params }) => ({
|
|
1475
|
+
profile: makeProfileInfo(fullProfile, params.id_token)
|
|
1476
|
+
});
|
|
1477
|
+
const provider = new MicrosoftAuthProvider({
|
|
1478
|
+
clientId,
|
|
1479
|
+
clientSecret,
|
|
1480
|
+
callbackUrl,
|
|
1481
|
+
authorizationUrl,
|
|
1482
|
+
tokenUrl,
|
|
1483
|
+
authHandler,
|
|
1484
|
+
signInResolver: (_a = options == null ? void 0 : options.signIn) == null ? void 0 : _a.resolver,
|
|
1485
|
+
logger,
|
|
1486
|
+
resolverContext
|
|
1487
|
+
});
|
|
1488
|
+
return OAuthAdapter.fromConfig(globalConfig, provider, {
|
|
1489
|
+
disableRefresh: false,
|
|
1490
|
+
providerId,
|
|
1491
|
+
callbackUrl
|
|
1492
|
+
});
|
|
1493
|
+
});
|
|
1494
|
+
},
|
|
1495
|
+
resolvers: {
|
|
1496
|
+
emailLocalPartMatchingUserEntityName: () => commonByEmailLocalPartResolver,
|
|
1497
|
+
emailMatchingUserEntityProfileEmail: () => commonByEmailResolver,
|
|
1498
|
+
emailMatchingUserEntityAnnotation() {
|
|
1499
|
+
return async (info, ctx) => {
|
|
1500
|
+
const { profile } = info;
|
|
1501
|
+
if (!profile.email) {
|
|
1502
|
+
throw new Error("Microsoft profile contained no email");
|
|
1503
|
+
}
|
|
1504
|
+
return ctx.signInWithCatalogUser({
|
|
1505
|
+
annotations: {
|
|
1506
|
+
"microsoft.com/email": profile.email
|
|
1507
|
+
}
|
|
1508
|
+
});
|
|
1509
|
+
};
|
|
1721
1510
|
}
|
|
1722
|
-
});
|
|
1723
|
-
const claims = getEntityClaims(entity);
|
|
1724
|
-
const token = await ctx.tokenIssuer.issueToken({ claims });
|
|
1725
|
-
return { id: entity.metadata.name, entity, token };
|
|
1726
|
-
};
|
|
1727
|
-
const microsoftDefaultSignInResolver = async (info, ctx) => {
|
|
1728
|
-
const { profile } = info;
|
|
1729
|
-
if (!profile.email) {
|
|
1730
|
-
throw new Error("Profile contained no email");
|
|
1731
1511
|
}
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
namespace: catalogModel.DEFAULT_NAMESPACE,
|
|
1736
|
-
name: userId
|
|
1737
|
-
});
|
|
1738
|
-
const token = await ctx.tokenIssuer.issueToken({
|
|
1739
|
-
claims: {
|
|
1740
|
-
sub: entityRef,
|
|
1741
|
-
ent: [entityRef]
|
|
1742
|
-
}
|
|
1743
|
-
});
|
|
1744
|
-
return { id: userId, token };
|
|
1745
|
-
};
|
|
1746
|
-
const createMicrosoftProvider = (options) => {
|
|
1747
|
-
return ({
|
|
1748
|
-
providerId,
|
|
1749
|
-
globalConfig,
|
|
1750
|
-
config,
|
|
1751
|
-
tokenIssuer,
|
|
1752
|
-
tokenManager,
|
|
1753
|
-
catalogApi,
|
|
1754
|
-
logger
|
|
1755
|
-
}) => OAuthEnvironmentHandler.mapConfig(config, (envConfig) => {
|
|
1756
|
-
var _a, _b;
|
|
1757
|
-
const clientId = envConfig.getString("clientId");
|
|
1758
|
-
const clientSecret = envConfig.getString("clientSecret");
|
|
1759
|
-
const tenantId = envConfig.getString("tenantId");
|
|
1760
|
-
const customCallbackUrl = envConfig.getOptionalString("callbackUrl");
|
|
1761
|
-
const callbackUrl = customCallbackUrl || `${globalConfig.baseUrl}/${providerId}/handler/frame`;
|
|
1762
|
-
const authorizationUrl = `https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/authorize`;
|
|
1763
|
-
const tokenUrl = `https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/token`;
|
|
1764
|
-
const catalogIdentityClient = new CatalogIdentityClient({
|
|
1765
|
-
catalogApi,
|
|
1766
|
-
tokenManager
|
|
1767
|
-
});
|
|
1768
|
-
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ fullProfile, params }) => ({
|
|
1769
|
-
profile: makeProfileInfo(fullProfile, params.id_token)
|
|
1770
|
-
});
|
|
1771
|
-
const signInResolverFn = (_b = (_a = options == null ? void 0 : options.signIn) == null ? void 0 : _a.resolver) != null ? _b : microsoftDefaultSignInResolver;
|
|
1772
|
-
const signInResolver = (info) => signInResolverFn(info, {
|
|
1773
|
-
catalogIdentityClient,
|
|
1774
|
-
tokenIssuer,
|
|
1775
|
-
logger
|
|
1776
|
-
});
|
|
1777
|
-
const provider = new MicrosoftAuthProvider({
|
|
1778
|
-
clientId,
|
|
1779
|
-
clientSecret,
|
|
1780
|
-
callbackUrl,
|
|
1781
|
-
authorizationUrl,
|
|
1782
|
-
tokenUrl,
|
|
1783
|
-
authHandler,
|
|
1784
|
-
signInResolver,
|
|
1785
|
-
catalogIdentityClient,
|
|
1786
|
-
logger,
|
|
1787
|
-
tokenIssuer
|
|
1788
|
-
});
|
|
1789
|
-
return OAuthAdapter.fromConfig(globalConfig, provider, {
|
|
1790
|
-
disableRefresh: false,
|
|
1791
|
-
providerId,
|
|
1792
|
-
tokenIssuer,
|
|
1793
|
-
callbackUrl
|
|
1794
|
-
});
|
|
1795
|
-
});
|
|
1796
|
-
};
|
|
1512
|
+
});
|
|
1513
|
+
const createMicrosoftProvider = microsoft.create;
|
|
1514
|
+
const microsoftEmailSignInResolver = microsoft.resolvers.emailMatchingUserEntityAnnotation();
|
|
1797
1515
|
|
|
1798
1516
|
class OAuth2AuthProvider {
|
|
1799
1517
|
constructor(options) {
|
|
1800
1518
|
this.signInResolver = options.signInResolver;
|
|
1801
1519
|
this.authHandler = options.authHandler;
|
|
1802
|
-
this.
|
|
1803
|
-
this.catalogIdentityClient = options.catalogIdentityClient;
|
|
1804
|
-
this.logger = options.logger;
|
|
1520
|
+
this.resolverContext = options.resolverContext;
|
|
1805
1521
|
this._strategy = new OAuth2Strategy.Strategy({
|
|
1806
1522
|
clientID: options.clientId,
|
|
1807
1523
|
clientSecret: options.clientSecret,
|
|
@@ -1853,12 +1569,7 @@ class OAuth2AuthProvider {
|
|
|
1853
1569
|
};
|
|
1854
1570
|
}
|
|
1855
1571
|
async handleResult(result) {
|
|
1856
|
-
const
|
|
1857
|
-
logger: this.logger,
|
|
1858
|
-
catalogIdentityClient: this.catalogIdentityClient,
|
|
1859
|
-
tokenIssuer: this.tokenIssuer
|
|
1860
|
-
};
|
|
1861
|
-
const { profile } = await this.authHandler(result, context);
|
|
1572
|
+
const { profile } = await this.authHandler(result, this.resolverContext);
|
|
1862
1573
|
const response = {
|
|
1863
1574
|
providerInfo: {
|
|
1864
1575
|
idToken: result.params.id_token,
|
|
@@ -1872,7 +1583,7 @@ class OAuth2AuthProvider {
|
|
|
1872
1583
|
response.backstageIdentity = await this.signInResolver({
|
|
1873
1584
|
result,
|
|
1874
1585
|
profile
|
|
1875
|
-
},
|
|
1586
|
+
}, this.resolverContext);
|
|
1876
1587
|
}
|
|
1877
1588
|
return response;
|
|
1878
1589
|
}
|
|
@@ -1880,87 +1591,48 @@ class OAuth2AuthProvider {
|
|
|
1880
1591
|
return Buffer.from(`${clientID}:${clientSecret}`).toString("base64");
|
|
1881
1592
|
}
|
|
1882
1593
|
}
|
|
1883
|
-
const
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
const callbackUrl = customCallbackUrl || `${globalConfig.baseUrl}/${providerId}/handler/frame`;
|
|
1917
|
-
const authorizationUrl = envConfig.getString("authorizationUrl");
|
|
1918
|
-
const tokenUrl = envConfig.getString("tokenUrl");
|
|
1919
|
-
const scope = envConfig.getOptionalString("scope");
|
|
1920
|
-
const includeBasicAuth = envConfig.getOptionalBoolean("includeBasicAuth");
|
|
1921
|
-
const disableRefresh = (_a = envConfig.getOptionalBoolean("disableRefresh")) != null ? _a : false;
|
|
1922
|
-
const catalogIdentityClient = new CatalogIdentityClient({
|
|
1923
|
-
catalogApi,
|
|
1924
|
-
tokenManager
|
|
1925
|
-
});
|
|
1926
|
-
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ fullProfile, params }) => ({
|
|
1927
|
-
profile: makeProfileInfo(fullProfile, params.id_token)
|
|
1928
|
-
});
|
|
1929
|
-
const signInResolverFn = (_c = (_b = options == null ? void 0 : options.signIn) == null ? void 0 : _b.resolver) != null ? _c : oAuth2DefaultSignInResolver;
|
|
1930
|
-
const signInResolver = (info) => signInResolverFn(info, {
|
|
1931
|
-
catalogIdentityClient,
|
|
1932
|
-
tokenIssuer,
|
|
1933
|
-
logger
|
|
1934
|
-
});
|
|
1935
|
-
const provider = new OAuth2AuthProvider({
|
|
1936
|
-
clientId,
|
|
1937
|
-
clientSecret,
|
|
1938
|
-
tokenIssuer,
|
|
1939
|
-
catalogIdentityClient,
|
|
1940
|
-
callbackUrl,
|
|
1941
|
-
signInResolver,
|
|
1942
|
-
authHandler,
|
|
1943
|
-
authorizationUrl,
|
|
1944
|
-
tokenUrl,
|
|
1945
|
-
scope,
|
|
1946
|
-
logger,
|
|
1947
|
-
includeBasicAuth
|
|
1948
|
-
});
|
|
1949
|
-
return OAuthAdapter.fromConfig(globalConfig, provider, {
|
|
1950
|
-
disableRefresh,
|
|
1951
|
-
providerId,
|
|
1952
|
-
tokenIssuer,
|
|
1953
|
-
callbackUrl
|
|
1594
|
+
const oauth2 = createAuthProviderIntegration({
|
|
1595
|
+
create(options) {
|
|
1596
|
+
return ({ providerId, globalConfig, config, resolverContext }) => OAuthEnvironmentHandler.mapConfig(config, (envConfig) => {
|
|
1597
|
+
var _a, _b;
|
|
1598
|
+
const clientId = envConfig.getString("clientId");
|
|
1599
|
+
const clientSecret = envConfig.getString("clientSecret");
|
|
1600
|
+
const customCallbackUrl = envConfig.getOptionalString("callbackUrl");
|
|
1601
|
+
const callbackUrl = customCallbackUrl || `${globalConfig.baseUrl}/${providerId}/handler/frame`;
|
|
1602
|
+
const authorizationUrl = envConfig.getString("authorizationUrl");
|
|
1603
|
+
const tokenUrl = envConfig.getString("tokenUrl");
|
|
1604
|
+
const scope = envConfig.getOptionalString("scope");
|
|
1605
|
+
const includeBasicAuth = envConfig.getOptionalBoolean("includeBasicAuth");
|
|
1606
|
+
const disableRefresh = (_a = envConfig.getOptionalBoolean("disableRefresh")) != null ? _a : false;
|
|
1607
|
+
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ fullProfile, params }) => ({
|
|
1608
|
+
profile: makeProfileInfo(fullProfile, params.id_token)
|
|
1609
|
+
});
|
|
1610
|
+
const provider = new OAuth2AuthProvider({
|
|
1611
|
+
clientId,
|
|
1612
|
+
clientSecret,
|
|
1613
|
+
callbackUrl,
|
|
1614
|
+
signInResolver: (_b = options == null ? void 0 : options.signIn) == null ? void 0 : _b.resolver,
|
|
1615
|
+
authHandler,
|
|
1616
|
+
authorizationUrl,
|
|
1617
|
+
tokenUrl,
|
|
1618
|
+
scope,
|
|
1619
|
+
includeBasicAuth,
|
|
1620
|
+
resolverContext
|
|
1621
|
+
});
|
|
1622
|
+
return OAuthAdapter.fromConfig(globalConfig, provider, {
|
|
1623
|
+
disableRefresh,
|
|
1624
|
+
providerId,
|
|
1625
|
+
callbackUrl
|
|
1626
|
+
});
|
|
1954
1627
|
});
|
|
1955
|
-
}
|
|
1956
|
-
};
|
|
1628
|
+
}
|
|
1629
|
+
});
|
|
1630
|
+
const createOAuth2Provider = oauth2.create;
|
|
1957
1631
|
|
|
1958
1632
|
const OAUTH2_PROXY_JWT_HEADER = "X-OAUTH2-PROXY-ID-TOKEN";
|
|
1959
1633
|
class Oauth2ProxyAuthProvider {
|
|
1960
1634
|
constructor(options) {
|
|
1961
|
-
this.
|
|
1962
|
-
this.logger = options.logger;
|
|
1963
|
-
this.tokenIssuer = options.tokenIssuer;
|
|
1635
|
+
this.resolverContext = options.resolverContext;
|
|
1964
1636
|
this.signInResolver = options.signInResolver;
|
|
1965
1637
|
this.authHandler = options.authHandler;
|
|
1966
1638
|
}
|
|
@@ -1973,25 +1645,18 @@ class Oauth2ProxyAuthProvider {
|
|
|
1973
1645
|
const response = await this.handleResult(result);
|
|
1974
1646
|
res.json(response);
|
|
1975
1647
|
} catch (e) {
|
|
1976
|
-
|
|
1977
|
-
res.status(401);
|
|
1978
|
-
res.end();
|
|
1648
|
+
throw new errors.AuthenticationError("Refresh failed", e);
|
|
1979
1649
|
}
|
|
1980
1650
|
}
|
|
1981
1651
|
start() {
|
|
1982
1652
|
return Promise.resolve(void 0);
|
|
1983
1653
|
}
|
|
1984
1654
|
async handleResult(result) {
|
|
1985
|
-
const
|
|
1986
|
-
logger: this.logger,
|
|
1987
|
-
tokenIssuer: this.tokenIssuer,
|
|
1988
|
-
catalogIdentityClient: this.catalogIdentityClient
|
|
1989
|
-
};
|
|
1990
|
-
const { profile } = await this.authHandler(result, ctx);
|
|
1655
|
+
const { profile } = await this.authHandler(result, this.resolverContext);
|
|
1991
1656
|
const backstageSignInResult = await this.signInResolver({
|
|
1992
1657
|
result,
|
|
1993
1658
|
profile
|
|
1994
|
-
},
|
|
1659
|
+
}, this.resolverContext);
|
|
1995
1660
|
return {
|
|
1996
1661
|
providerInfo: {
|
|
1997
1662
|
accessToken: result.accessToken
|
|
@@ -2006,28 +1671,27 @@ class Oauth2ProxyAuthProvider {
|
|
|
2006
1671
|
if (!jwt) {
|
|
2007
1672
|
throw new errors.AuthenticationError(`Missing or in incorrect format - Oauth2Proxy OIDC header: ${OAUTH2_PROXY_JWT_HEADER}`);
|
|
2008
1673
|
}
|
|
2009
|
-
const decodedJWT = jose.
|
|
1674
|
+
const decodedJWT = jose.decodeJwt(jwt);
|
|
2010
1675
|
return {
|
|
2011
1676
|
fullProfile: decodedJWT,
|
|
2012
1677
|
accessToken: jwt
|
|
2013
1678
|
};
|
|
2014
1679
|
}
|
|
2015
1680
|
}
|
|
2016
|
-
const
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
};
|
|
1681
|
+
const oauth2Proxy = createAuthProviderIntegration({
|
|
1682
|
+
create(options) {
|
|
1683
|
+
return ({ resolverContext }) => {
|
|
1684
|
+
const signInResolver = options.signIn.resolver;
|
|
1685
|
+
const authHandler = options.authHandler;
|
|
1686
|
+
return new Oauth2ProxyAuthProvider({
|
|
1687
|
+
resolverContext,
|
|
1688
|
+
signInResolver,
|
|
1689
|
+
authHandler
|
|
1690
|
+
});
|
|
1691
|
+
};
|
|
1692
|
+
}
|
|
1693
|
+
});
|
|
1694
|
+
const createOauth2ProxyProvider = oauth2Proxy.create;
|
|
2031
1695
|
|
|
2032
1696
|
class OidcAuthProvider {
|
|
2033
1697
|
constructor(options) {
|
|
@@ -2036,9 +1700,7 @@ class OidcAuthProvider {
|
|
|
2036
1700
|
this.prompt = options.prompt;
|
|
2037
1701
|
this.signInResolver = options.signInResolver;
|
|
2038
1702
|
this.authHandler = options.authHandler;
|
|
2039
|
-
this.
|
|
2040
|
-
this.catalogIdentityClient = options.catalogIdentityClient;
|
|
2041
|
-
this.logger = options.logger;
|
|
1703
|
+
this.resolverContext = options.resolverContext;
|
|
2042
1704
|
}
|
|
2043
1705
|
async start(req) {
|
|
2044
1706
|
const { strategy } = await this.implementation;
|
|
@@ -2098,12 +1760,7 @@ class OidcAuthProvider {
|
|
|
2098
1760
|
return { strategy, client };
|
|
2099
1761
|
}
|
|
2100
1762
|
async handleResult(result) {
|
|
2101
|
-
const
|
|
2102
|
-
logger: this.logger,
|
|
2103
|
-
catalogIdentityClient: this.catalogIdentityClient,
|
|
2104
|
-
tokenIssuer: this.tokenIssuer
|
|
2105
|
-
};
|
|
2106
|
-
const { profile } = await this.authHandler(result, context);
|
|
1763
|
+
const { profile } = await this.authHandler(result, this.resolverContext);
|
|
2107
1764
|
const response = {
|
|
2108
1765
|
providerInfo: {
|
|
2109
1766
|
idToken: result.tokenset.id_token,
|
|
@@ -2117,92 +1774,55 @@ class OidcAuthProvider {
|
|
|
2117
1774
|
response.backstageIdentity = await this.signInResolver({
|
|
2118
1775
|
result,
|
|
2119
1776
|
profile
|
|
2120
|
-
},
|
|
1777
|
+
}, this.resolverContext);
|
|
2121
1778
|
}
|
|
2122
1779
|
return response;
|
|
2123
1780
|
}
|
|
2124
1781
|
}
|
|
2125
|
-
const
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
};
|
|
2144
|
-
const
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
const scope = envConfig.getOptionalString("scope");
|
|
2162
|
-
const prompt = envConfig.getOptionalString("prompt");
|
|
2163
|
-
const catalogIdentityClient = new CatalogIdentityClient({
|
|
2164
|
-
catalogApi,
|
|
2165
|
-
tokenManager
|
|
2166
|
-
});
|
|
2167
|
-
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ userinfo }) => ({
|
|
2168
|
-
profile: {
|
|
2169
|
-
displayName: userinfo.name,
|
|
2170
|
-
email: userinfo.email,
|
|
2171
|
-
picture: userinfo.picture
|
|
2172
|
-
}
|
|
2173
|
-
});
|
|
2174
|
-
const signInResolverFn = (_b = (_a = options == null ? void 0 : options.signIn) == null ? void 0 : _a.resolver) != null ? _b : oidcDefaultSignInResolver;
|
|
2175
|
-
const signInResolver = (info) => signInResolverFn(info, {
|
|
2176
|
-
catalogIdentityClient,
|
|
2177
|
-
tokenIssuer,
|
|
2178
|
-
logger
|
|
2179
|
-
});
|
|
2180
|
-
const provider = new OidcAuthProvider({
|
|
2181
|
-
clientId,
|
|
2182
|
-
clientSecret,
|
|
2183
|
-
callbackUrl,
|
|
2184
|
-
tokenSignedResponseAlg,
|
|
2185
|
-
metadataUrl,
|
|
2186
|
-
scope,
|
|
2187
|
-
prompt,
|
|
2188
|
-
signInResolver,
|
|
2189
|
-
authHandler,
|
|
2190
|
-
logger,
|
|
2191
|
-
tokenIssuer,
|
|
2192
|
-
catalogIdentityClient
|
|
2193
|
-
});
|
|
2194
|
-
return OAuthAdapter.fromConfig(globalConfig, provider, {
|
|
2195
|
-
disableRefresh: false,
|
|
2196
|
-
providerId,
|
|
2197
|
-
tokenIssuer,
|
|
2198
|
-
callbackUrl
|
|
1782
|
+
const oidc = createAuthProviderIntegration({
|
|
1783
|
+
create(options) {
|
|
1784
|
+
return ({ providerId, globalConfig, config, resolverContext }) => OAuthEnvironmentHandler.mapConfig(config, (envConfig) => {
|
|
1785
|
+
var _a;
|
|
1786
|
+
const clientId = envConfig.getString("clientId");
|
|
1787
|
+
const clientSecret = envConfig.getString("clientSecret");
|
|
1788
|
+
const customCallbackUrl = envConfig.getOptionalString("callbackUrl");
|
|
1789
|
+
const callbackUrl = customCallbackUrl || `${globalConfig.baseUrl}/${providerId}/handler/frame`;
|
|
1790
|
+
const metadataUrl = envConfig.getString("metadataUrl");
|
|
1791
|
+
const tokenSignedResponseAlg = envConfig.getOptionalString("tokenSignedResponseAlg");
|
|
1792
|
+
const scope = envConfig.getOptionalString("scope");
|
|
1793
|
+
const prompt = envConfig.getOptionalString("prompt");
|
|
1794
|
+
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ userinfo }) => ({
|
|
1795
|
+
profile: {
|
|
1796
|
+
displayName: userinfo.name,
|
|
1797
|
+
email: userinfo.email,
|
|
1798
|
+
picture: userinfo.picture
|
|
1799
|
+
}
|
|
1800
|
+
});
|
|
1801
|
+
const provider = new OidcAuthProvider({
|
|
1802
|
+
clientId,
|
|
1803
|
+
clientSecret,
|
|
1804
|
+
callbackUrl,
|
|
1805
|
+
tokenSignedResponseAlg,
|
|
1806
|
+
metadataUrl,
|
|
1807
|
+
scope,
|
|
1808
|
+
prompt,
|
|
1809
|
+
signInResolver: (_a = options == null ? void 0 : options.signIn) == null ? void 0 : _a.resolver,
|
|
1810
|
+
authHandler,
|
|
1811
|
+
resolverContext
|
|
1812
|
+
});
|
|
1813
|
+
return OAuthAdapter.fromConfig(globalConfig, provider, {
|
|
1814
|
+
disableRefresh: false,
|
|
1815
|
+
providerId,
|
|
1816
|
+
callbackUrl
|
|
1817
|
+
});
|
|
2199
1818
|
});
|
|
2200
|
-
}
|
|
2201
|
-
};
|
|
1819
|
+
}
|
|
1820
|
+
});
|
|
1821
|
+
const createOidcProvider = oidc.create;
|
|
2202
1822
|
|
|
2203
1823
|
class OktaAuthProvider {
|
|
2204
1824
|
constructor(options) {
|
|
2205
|
-
this.
|
|
1825
|
+
this.store = {
|
|
2206
1826
|
store(_req, cb) {
|
|
2207
1827
|
cb(null, null);
|
|
2208
1828
|
},
|
|
@@ -2210,18 +1830,16 @@ class OktaAuthProvider {
|
|
|
2210
1830
|
cb(null, true);
|
|
2211
1831
|
}
|
|
2212
1832
|
};
|
|
2213
|
-
this.
|
|
2214
|
-
this.
|
|
2215
|
-
this.
|
|
2216
|
-
this.
|
|
2217
|
-
this._logger = options.logger;
|
|
2218
|
-
this._strategy = new passportOktaOauth.Strategy({
|
|
1833
|
+
this.signInResolver = options.signInResolver;
|
|
1834
|
+
this.authHandler = options.authHandler;
|
|
1835
|
+
this.resolverContext = options.resolverContext;
|
|
1836
|
+
this.strategy = new passportOktaOauth.Strategy({
|
|
2219
1837
|
clientID: options.clientId,
|
|
2220
1838
|
clientSecret: options.clientSecret,
|
|
2221
1839
|
callbackURL: options.callbackUrl,
|
|
2222
1840
|
audience: options.audience,
|
|
2223
1841
|
passReqToCallback: false,
|
|
2224
|
-
store: this.
|
|
1842
|
+
store: this.store,
|
|
2225
1843
|
response_type: "code"
|
|
2226
1844
|
}, (accessToken, refreshToken, params, fullProfile, done) => {
|
|
2227
1845
|
done(void 0, {
|
|
@@ -2235,7 +1853,7 @@ class OktaAuthProvider {
|
|
|
2235
1853
|
});
|
|
2236
1854
|
}
|
|
2237
1855
|
async start(req) {
|
|
2238
|
-
return await executeRedirectStrategy(req, this.
|
|
1856
|
+
return await executeRedirectStrategy(req, this.strategy, {
|
|
2239
1857
|
accessType: "offline",
|
|
2240
1858
|
prompt: "consent",
|
|
2241
1859
|
scope: req.scope,
|
|
@@ -2243,15 +1861,15 @@ class OktaAuthProvider {
|
|
|
2243
1861
|
});
|
|
2244
1862
|
}
|
|
2245
1863
|
async handler(req) {
|
|
2246
|
-
const { result, privateInfo } = await executeFrameHandlerStrategy(req, this.
|
|
1864
|
+
const { result, privateInfo } = await executeFrameHandlerStrategy(req, this.strategy);
|
|
2247
1865
|
return {
|
|
2248
1866
|
response: await this.handleResult(result),
|
|
2249
1867
|
refreshToken: privateInfo.refreshToken
|
|
2250
1868
|
};
|
|
2251
1869
|
}
|
|
2252
1870
|
async refresh(req) {
|
|
2253
|
-
const { accessToken, refreshToken, params } = await executeRefreshTokenStrategy(this.
|
|
2254
|
-
const fullProfile = await executeFetchUserProfileStrategy(this.
|
|
1871
|
+
const { accessToken, refreshToken, params } = await executeRefreshTokenStrategy(this.strategy, req.refreshToken, req.scope);
|
|
1872
|
+
const fullProfile = await executeFetchUserProfileStrategy(this.strategy, accessToken);
|
|
2255
1873
|
return {
|
|
2256
1874
|
response: await this.handleResult({
|
|
2257
1875
|
fullProfile,
|
|
@@ -2262,12 +1880,7 @@ class OktaAuthProvider {
|
|
|
2262
1880
|
};
|
|
2263
1881
|
}
|
|
2264
1882
|
async handleResult(result) {
|
|
2265
|
-
const
|
|
2266
|
-
logger: this._logger,
|
|
2267
|
-
catalogIdentityClient: this._catalogIdentityClient,
|
|
2268
|
-
tokenIssuer: this._tokenIssuer
|
|
2269
|
-
};
|
|
2270
|
-
const { profile } = await this._authHandler(result, context);
|
|
1883
|
+
const { profile } = await this.authHandler(result, this.resolverContext);
|
|
2271
1884
|
const response = {
|
|
2272
1885
|
providerInfo: {
|
|
2273
1886
|
idToken: result.params.id_token,
|
|
@@ -2277,107 +1890,72 @@ class OktaAuthProvider {
|
|
|
2277
1890
|
},
|
|
2278
1891
|
profile
|
|
2279
1892
|
};
|
|
2280
|
-
if (this.
|
|
2281
|
-
response.backstageIdentity = await this.
|
|
1893
|
+
if (this.signInResolver) {
|
|
1894
|
+
response.backstageIdentity = await this.signInResolver({
|
|
2282
1895
|
result,
|
|
2283
1896
|
profile
|
|
2284
|
-
},
|
|
1897
|
+
}, this.resolverContext);
|
|
2285
1898
|
}
|
|
2286
1899
|
return response;
|
|
2287
1900
|
}
|
|
2288
1901
|
}
|
|
2289
|
-
const
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
1902
|
+
const okta = createAuthProviderIntegration({
|
|
1903
|
+
create(options) {
|
|
1904
|
+
return ({ providerId, globalConfig, config, resolverContext }) => OAuthEnvironmentHandler.mapConfig(config, (envConfig) => {
|
|
1905
|
+
var _a;
|
|
1906
|
+
const clientId = envConfig.getString("clientId");
|
|
1907
|
+
const clientSecret = envConfig.getString("clientSecret");
|
|
1908
|
+
const audience = envConfig.getString("audience");
|
|
1909
|
+
const customCallbackUrl = envConfig.getOptionalString("callbackUrl");
|
|
1910
|
+
const callbackUrl = customCallbackUrl || `${globalConfig.baseUrl}/${providerId}/handler/frame`;
|
|
1911
|
+
if (!audience.startsWith("https://")) {
|
|
1912
|
+
throw new Error("URL for 'audience' must start with 'https://'.");
|
|
1913
|
+
}
|
|
1914
|
+
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ fullProfile, params }) => ({
|
|
1915
|
+
profile: makeProfileInfo(fullProfile, params.id_token)
|
|
1916
|
+
});
|
|
1917
|
+
const provider = new OktaAuthProvider({
|
|
1918
|
+
audience,
|
|
1919
|
+
clientId,
|
|
1920
|
+
clientSecret,
|
|
1921
|
+
callbackUrl,
|
|
1922
|
+
authHandler,
|
|
1923
|
+
signInResolver: (_a = options == null ? void 0 : options.signIn) == null ? void 0 : _a.resolver,
|
|
1924
|
+
resolverContext
|
|
1925
|
+
});
|
|
1926
|
+
return OAuthAdapter.fromConfig(globalConfig, provider, {
|
|
1927
|
+
disableRefresh: false,
|
|
1928
|
+
providerId,
|
|
1929
|
+
callbackUrl
|
|
1930
|
+
});
|
|
1931
|
+
});
|
|
1932
|
+
},
|
|
1933
|
+
resolvers: {
|
|
1934
|
+
emailLocalPartMatchingUserEntityName: () => commonByEmailLocalPartResolver,
|
|
1935
|
+
emailMatchingUserEntityProfileEmail: () => commonByEmailResolver,
|
|
1936
|
+
emailMatchingUserEntityAnnotation() {
|
|
1937
|
+
return async (info, ctx) => {
|
|
1938
|
+
const { profile } = info;
|
|
1939
|
+
if (!profile.email) {
|
|
1940
|
+
throw new Error("Okta profile contained no email");
|
|
1941
|
+
}
|
|
1942
|
+
return ctx.signInWithCatalogUser({
|
|
1943
|
+
annotations: {
|
|
1944
|
+
"okta.com/email": profile.email
|
|
1945
|
+
}
|
|
1946
|
+
});
|
|
1947
|
+
};
|
|
2297
1948
|
}
|
|
2298
|
-
});
|
|
2299
|
-
const claims = getEntityClaims(entity);
|
|
2300
|
-
const token = await ctx.tokenIssuer.issueToken({ claims });
|
|
2301
|
-
return { id: entity.metadata.name, entity, token };
|
|
2302
|
-
};
|
|
2303
|
-
const oktaDefaultSignInResolver = async (info, ctx) => {
|
|
2304
|
-
const { profile } = info;
|
|
2305
|
-
if (!profile.email) {
|
|
2306
|
-
throw new Error("Okta profile contained no email");
|
|
2307
1949
|
}
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
namespace: catalogModel.DEFAULT_NAMESPACE,
|
|
2312
|
-
name: userId
|
|
2313
|
-
});
|
|
2314
|
-
const token = await ctx.tokenIssuer.issueToken({
|
|
2315
|
-
claims: {
|
|
2316
|
-
sub: entityRef,
|
|
2317
|
-
ent: [entityRef]
|
|
2318
|
-
}
|
|
2319
|
-
});
|
|
2320
|
-
return { id: userId, token };
|
|
2321
|
-
};
|
|
2322
|
-
const createOktaProvider = (_options) => {
|
|
2323
|
-
return ({
|
|
2324
|
-
providerId,
|
|
2325
|
-
globalConfig,
|
|
2326
|
-
config,
|
|
2327
|
-
tokenIssuer,
|
|
2328
|
-
tokenManager,
|
|
2329
|
-
catalogApi,
|
|
2330
|
-
logger
|
|
2331
|
-
}) => OAuthEnvironmentHandler.mapConfig(config, (envConfig) => {
|
|
2332
|
-
var _a, _b;
|
|
2333
|
-
const clientId = envConfig.getString("clientId");
|
|
2334
|
-
const clientSecret = envConfig.getString("clientSecret");
|
|
2335
|
-
const audience = envConfig.getString("audience");
|
|
2336
|
-
const customCallbackUrl = envConfig.getOptionalString("callbackUrl");
|
|
2337
|
-
const callbackUrl = customCallbackUrl || `${globalConfig.baseUrl}/${providerId}/handler/frame`;
|
|
2338
|
-
if (!audience.startsWith("https://")) {
|
|
2339
|
-
throw new Error("URL for 'audience' must start with 'https://'.");
|
|
2340
|
-
}
|
|
2341
|
-
const catalogIdentityClient = new CatalogIdentityClient({
|
|
2342
|
-
catalogApi,
|
|
2343
|
-
tokenManager
|
|
2344
|
-
});
|
|
2345
|
-
const authHandler = (_options == null ? void 0 : _options.authHandler) ? _options.authHandler : async ({ fullProfile, params }) => ({
|
|
2346
|
-
profile: makeProfileInfo(fullProfile, params.id_token)
|
|
2347
|
-
});
|
|
2348
|
-
const signInResolverFn = (_b = (_a = _options == null ? void 0 : _options.signIn) == null ? void 0 : _a.resolver) != null ? _b : oktaDefaultSignInResolver;
|
|
2349
|
-
const signInResolver = (info) => signInResolverFn(info, {
|
|
2350
|
-
catalogIdentityClient,
|
|
2351
|
-
tokenIssuer,
|
|
2352
|
-
logger
|
|
2353
|
-
});
|
|
2354
|
-
const provider = new OktaAuthProvider({
|
|
2355
|
-
audience,
|
|
2356
|
-
clientId,
|
|
2357
|
-
clientSecret,
|
|
2358
|
-
callbackUrl,
|
|
2359
|
-
authHandler,
|
|
2360
|
-
signInResolver,
|
|
2361
|
-
tokenIssuer,
|
|
2362
|
-
catalogIdentityClient,
|
|
2363
|
-
logger
|
|
2364
|
-
});
|
|
2365
|
-
return OAuthAdapter.fromConfig(globalConfig, provider, {
|
|
2366
|
-
disableRefresh: false,
|
|
2367
|
-
providerId,
|
|
2368
|
-
tokenIssuer,
|
|
2369
|
-
callbackUrl
|
|
2370
|
-
});
|
|
2371
|
-
});
|
|
2372
|
-
};
|
|
1950
|
+
});
|
|
1951
|
+
const createOktaProvider = okta.create;
|
|
1952
|
+
const oktaEmailSignInResolver = okta.resolvers.emailMatchingUserEntityAnnotation();
|
|
2373
1953
|
|
|
2374
1954
|
class OneLoginProvider {
|
|
2375
1955
|
constructor(options) {
|
|
2376
1956
|
this.signInResolver = options.signInResolver;
|
|
2377
1957
|
this.authHandler = options.authHandler;
|
|
2378
|
-
this.
|
|
2379
|
-
this.catalogIdentityClient = options.catalogIdentityClient;
|
|
2380
|
-
this.logger = options.logger;
|
|
1958
|
+
this.resolverContext = options.resolverContext;
|
|
2381
1959
|
this._strategy = new passportOneloginOauth.Strategy({
|
|
2382
1960
|
issuer: options.issuer,
|
|
2383
1961
|
clientID: options.clientId,
|
|
@@ -2423,12 +2001,7 @@ class OneLoginProvider {
|
|
|
2423
2001
|
};
|
|
2424
2002
|
}
|
|
2425
2003
|
async handleResult(result) {
|
|
2426
|
-
const
|
|
2427
|
-
logger: this.logger,
|
|
2428
|
-
catalogIdentityClient: this.catalogIdentityClient,
|
|
2429
|
-
tokenIssuer: this.tokenIssuer
|
|
2430
|
-
};
|
|
2431
|
-
const { profile } = await this.authHandler(result, context);
|
|
2004
|
+
const { profile } = await this.authHandler(result, this.resolverContext);
|
|
2432
2005
|
const response = {
|
|
2433
2006
|
providerInfo: {
|
|
2434
2007
|
idToken: result.params.id_token,
|
|
@@ -2442,71 +2015,48 @@ class OneLoginProvider {
|
|
|
2442
2015
|
response.backstageIdentity = await this.signInResolver({
|
|
2443
2016
|
result,
|
|
2444
2017
|
profile
|
|
2445
|
-
},
|
|
2018
|
+
}, this.resolverContext);
|
|
2446
2019
|
}
|
|
2447
2020
|
return response;
|
|
2448
2021
|
}
|
|
2449
2022
|
}
|
|
2450
|
-
const
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
const
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
tokenManager
|
|
2477
|
-
});
|
|
2478
|
-
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ fullProfile, params }) => ({
|
|
2479
|
-
profile: makeProfileInfo(fullProfile, params.id_token)
|
|
2480
|
-
});
|
|
2481
|
-
const signInResolver = (_b = (_a = options == null ? void 0 : options.signIn) == null ? void 0 : _a.resolver) != null ? _b : defaultSignInResolver;
|
|
2482
|
-
const provider = new OneLoginProvider({
|
|
2483
|
-
clientId,
|
|
2484
|
-
clientSecret,
|
|
2485
|
-
callbackUrl,
|
|
2486
|
-
issuer,
|
|
2487
|
-
authHandler,
|
|
2488
|
-
signInResolver,
|
|
2489
|
-
tokenIssuer,
|
|
2490
|
-
catalogIdentityClient,
|
|
2491
|
-
logger
|
|
2492
|
-
});
|
|
2493
|
-
return OAuthAdapter.fromConfig(globalConfig, provider, {
|
|
2494
|
-
disableRefresh: false,
|
|
2495
|
-
providerId,
|
|
2496
|
-
tokenIssuer,
|
|
2497
|
-
callbackUrl
|
|
2023
|
+
const onelogin = createAuthProviderIntegration({
|
|
2024
|
+
create(options) {
|
|
2025
|
+
return ({ providerId, globalConfig, config, resolverContext }) => OAuthEnvironmentHandler.mapConfig(config, (envConfig) => {
|
|
2026
|
+
var _a;
|
|
2027
|
+
const clientId = envConfig.getString("clientId");
|
|
2028
|
+
const clientSecret = envConfig.getString("clientSecret");
|
|
2029
|
+
const issuer = envConfig.getString("issuer");
|
|
2030
|
+
const customCallbackUrl = envConfig.getOptionalString("callbackUrl");
|
|
2031
|
+
const callbackUrl = customCallbackUrl || `${globalConfig.baseUrl}/${providerId}/handler/frame`;
|
|
2032
|
+
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ fullProfile, params }) => ({
|
|
2033
|
+
profile: makeProfileInfo(fullProfile, params.id_token)
|
|
2034
|
+
});
|
|
2035
|
+
const provider = new OneLoginProvider({
|
|
2036
|
+
clientId,
|
|
2037
|
+
clientSecret,
|
|
2038
|
+
callbackUrl,
|
|
2039
|
+
issuer,
|
|
2040
|
+
authHandler,
|
|
2041
|
+
signInResolver: (_a = options == null ? void 0 : options.signIn) == null ? void 0 : _a.resolver,
|
|
2042
|
+
resolverContext
|
|
2043
|
+
});
|
|
2044
|
+
return OAuthAdapter.fromConfig(globalConfig, provider, {
|
|
2045
|
+
disableRefresh: false,
|
|
2046
|
+
providerId,
|
|
2047
|
+
callbackUrl
|
|
2048
|
+
});
|
|
2498
2049
|
});
|
|
2499
|
-
}
|
|
2500
|
-
};
|
|
2050
|
+
}
|
|
2051
|
+
});
|
|
2052
|
+
const createOneLoginProvider = onelogin.create;
|
|
2501
2053
|
|
|
2502
2054
|
class SamlAuthProvider {
|
|
2503
2055
|
constructor(options) {
|
|
2504
2056
|
this.appUrl = options.appUrl;
|
|
2505
2057
|
this.signInResolver = options.signInResolver;
|
|
2506
2058
|
this.authHandler = options.authHandler;
|
|
2507
|
-
this.
|
|
2508
|
-
this.catalogIdentityClient = options.catalogIdentityClient;
|
|
2509
|
-
this.logger = options.logger;
|
|
2059
|
+
this.resolverContext = options.resolverContext;
|
|
2510
2060
|
this.strategy = new passportSaml.Strategy({ ...options }, (fullProfile, done) => {
|
|
2511
2061
|
done(void 0, { fullProfile });
|
|
2512
2062
|
});
|
|
@@ -2517,13 +2067,8 @@ class SamlAuthProvider {
|
|
|
2517
2067
|
}
|
|
2518
2068
|
async frameHandler(req, res) {
|
|
2519
2069
|
try {
|
|
2520
|
-
const context = {
|
|
2521
|
-
logger: this.logger,
|
|
2522
|
-
catalogIdentityClient: this.catalogIdentityClient,
|
|
2523
|
-
tokenIssuer: this.tokenIssuer
|
|
2524
|
-
};
|
|
2525
2070
|
const { result } = await executeFrameHandlerStrategy(req, this.strategy);
|
|
2526
|
-
const { profile } = await this.authHandler(result,
|
|
2071
|
+
const { profile } = await this.authHandler(result, this.resolverContext);
|
|
2527
2072
|
const response = {
|
|
2528
2073
|
profile,
|
|
2529
2074
|
providerInfo: {}
|
|
@@ -2532,7 +2077,7 @@ class SamlAuthProvider {
|
|
|
2532
2077
|
const signInResponse = await this.signInResolver({
|
|
2533
2078
|
result,
|
|
2534
2079
|
profile
|
|
2535
|
-
},
|
|
2080
|
+
}, this.resolverContext);
|
|
2536
2081
|
response.backstageIdentity = prepareBackstageIdentityResponse(signInResponse);
|
|
2537
2082
|
}
|
|
2538
2083
|
return postMessageResponse(res, this.appUrl, {
|
|
@@ -2551,71 +2096,53 @@ class SamlAuthProvider {
|
|
|
2551
2096
|
res.end();
|
|
2552
2097
|
}
|
|
2553
2098
|
}
|
|
2554
|
-
const
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2099
|
+
const saml = createAuthProviderIntegration({
|
|
2100
|
+
create(options) {
|
|
2101
|
+
return ({ providerId, globalConfig, config, resolverContext }) => {
|
|
2102
|
+
var _a;
|
|
2103
|
+
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ fullProfile }) => ({
|
|
2104
|
+
profile: {
|
|
2105
|
+
email: fullProfile.email,
|
|
2106
|
+
displayName: fullProfile.displayName
|
|
2107
|
+
}
|
|
2108
|
+
});
|
|
2109
|
+
return new SamlAuthProvider({
|
|
2110
|
+
callbackUrl: `${globalConfig.baseUrl}/${providerId}/handler/frame`,
|
|
2111
|
+
entryPoint: config.getString("entryPoint"),
|
|
2112
|
+
logoutUrl: config.getOptionalString("logoutUrl"),
|
|
2113
|
+
audience: config.getOptionalString("audience"),
|
|
2114
|
+
issuer: config.getString("issuer"),
|
|
2115
|
+
cert: config.getString("cert"),
|
|
2116
|
+
privateKey: config.getOptionalString("privateKey"),
|
|
2117
|
+
authnContext: config.getOptionalStringArray("authnContext"),
|
|
2118
|
+
identifierFormat: config.getOptionalString("identifierFormat"),
|
|
2119
|
+
decryptionPvk: config.getOptionalString("decryptionPvk"),
|
|
2120
|
+
signatureAlgorithm: config.getOptionalString("signatureAlgorithm"),
|
|
2121
|
+
digestAlgorithm: config.getOptionalString("digestAlgorithm"),
|
|
2122
|
+
acceptedClockSkewMs: config.getOptionalNumber("acceptedClockSkewMs"),
|
|
2123
|
+
appUrl: globalConfig.appUrl,
|
|
2124
|
+
authHandler,
|
|
2125
|
+
signInResolver: (_a = options == null ? void 0 : options.signIn) == null ? void 0 : _a.resolver,
|
|
2126
|
+
resolverContext
|
|
2127
|
+
});
|
|
2128
|
+
};
|
|
2129
|
+
},
|
|
2130
|
+
resolvers: {
|
|
2131
|
+
nameIdMatchingUserEntityName() {
|
|
2132
|
+
return async (info, ctx) => {
|
|
2133
|
+
const id = info.result.fullProfile.nameID;
|
|
2134
|
+
if (!id) {
|
|
2135
|
+
throw new errors.AuthenticationError("No nameID found in SAML response");
|
|
2136
|
+
}
|
|
2137
|
+
return ctx.signInWithCatalogUser({
|
|
2138
|
+
entityRef: { name: id }
|
|
2139
|
+
});
|
|
2140
|
+
};
|
|
2565
2141
|
}
|
|
2566
|
-
}
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
const
|
|
2570
|
-
return ({
|
|
2571
|
-
providerId,
|
|
2572
|
-
globalConfig,
|
|
2573
|
-
config,
|
|
2574
|
-
tokenIssuer,
|
|
2575
|
-
tokenManager,
|
|
2576
|
-
catalogApi,
|
|
2577
|
-
logger
|
|
2578
|
-
}) => {
|
|
2579
|
-
var _a, _b;
|
|
2580
|
-
const catalogIdentityClient = new CatalogIdentityClient({
|
|
2581
|
-
catalogApi,
|
|
2582
|
-
tokenManager
|
|
2583
|
-
});
|
|
2584
|
-
const authHandler = (options == null ? void 0 : options.authHandler) ? options.authHandler : async ({ fullProfile }) => ({
|
|
2585
|
-
profile: {
|
|
2586
|
-
email: fullProfile.email,
|
|
2587
|
-
displayName: fullProfile.displayName
|
|
2588
|
-
}
|
|
2589
|
-
});
|
|
2590
|
-
const signInResolverFn = (_b = (_a = options == null ? void 0 : options.signIn) == null ? void 0 : _a.resolver) != null ? _b : samlDefaultSignInResolver;
|
|
2591
|
-
const signInResolver = (info) => signInResolverFn(info, {
|
|
2592
|
-
catalogIdentityClient,
|
|
2593
|
-
tokenIssuer,
|
|
2594
|
-
logger
|
|
2595
|
-
});
|
|
2596
|
-
return new SamlAuthProvider({
|
|
2597
|
-
callbackUrl: `${globalConfig.baseUrl}/${providerId}/handler/frame`,
|
|
2598
|
-
entryPoint: config.getString("entryPoint"),
|
|
2599
|
-
logoutUrl: config.getOptionalString("logoutUrl"),
|
|
2600
|
-
audience: config.getOptionalString("audience"),
|
|
2601
|
-
issuer: config.getString("issuer"),
|
|
2602
|
-
cert: config.getString("cert"),
|
|
2603
|
-
privateKey: config.getOptionalString("privateKey"),
|
|
2604
|
-
authnContext: config.getOptionalStringArray("authnContext"),
|
|
2605
|
-
identifierFormat: config.getOptionalString("identifierFormat"),
|
|
2606
|
-
decryptionPvk: config.getOptionalString("decryptionPvk"),
|
|
2607
|
-
signatureAlgorithm: config.getOptionalString("signatureAlgorithm"),
|
|
2608
|
-
digestAlgorithm: config.getOptionalString("digestAlgorithm"),
|
|
2609
|
-
acceptedClockSkewMs: config.getOptionalNumber("acceptedClockSkewMs"),
|
|
2610
|
-
tokenIssuer,
|
|
2611
|
-
appUrl: globalConfig.appUrl,
|
|
2612
|
-
authHandler,
|
|
2613
|
-
signInResolver,
|
|
2614
|
-
logger,
|
|
2615
|
-
catalogIdentityClient
|
|
2616
|
-
});
|
|
2617
|
-
};
|
|
2618
|
-
};
|
|
2142
|
+
}
|
|
2143
|
+
});
|
|
2144
|
+
const createSamlProvider = saml.create;
|
|
2145
|
+
const samlNameIdEntityNameSignInResolver = saml.resolvers.nameIdMatchingUserEntityName();
|
|
2619
2146
|
|
|
2620
2147
|
const IAP_JWT_HEADER = "x-goog-iap-jwt-assertion";
|
|
2621
2148
|
|
|
@@ -2661,9 +2188,7 @@ class GcpIapProvider {
|
|
|
2661
2188
|
this.authHandler = options.authHandler;
|
|
2662
2189
|
this.signInResolver = options.signInResolver;
|
|
2663
2190
|
this.tokenValidator = options.tokenValidator;
|
|
2664
|
-
this.
|
|
2665
|
-
this.catalogIdentityClient = options.catalogIdentityClient;
|
|
2666
|
-
this.logger = options.logger;
|
|
2191
|
+
this.resolverContext = options.resolverContext;
|
|
2667
2192
|
}
|
|
2668
2193
|
async start() {
|
|
2669
2194
|
}
|
|
@@ -2671,13 +2196,8 @@ class GcpIapProvider {
|
|
|
2671
2196
|
}
|
|
2672
2197
|
async refresh(req, res) {
|
|
2673
2198
|
const result = await parseRequestToken(req.header(IAP_JWT_HEADER), this.tokenValidator);
|
|
2674
|
-
const
|
|
2675
|
-
|
|
2676
|
-
catalogIdentityClient: this.catalogIdentityClient,
|
|
2677
|
-
tokenIssuer: this.tokenIssuer
|
|
2678
|
-
};
|
|
2679
|
-
const { profile } = await this.authHandler(result, context);
|
|
2680
|
-
const backstageIdentity = await this.signInResolver({ profile, result }, context);
|
|
2199
|
+
const { profile } = await this.authHandler(result, this.resolverContext);
|
|
2200
|
+
const backstageIdentity = await this.signInResolver({ profile, result }, this.resolverContext);
|
|
2681
2201
|
const response = {
|
|
2682
2202
|
providerInfo: { iapToken: result.iapToken },
|
|
2683
2203
|
profile,
|
|
@@ -2686,27 +2206,42 @@ class GcpIapProvider {
|
|
|
2686
2206
|
res.json(response);
|
|
2687
2207
|
}
|
|
2688
2208
|
}
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2209
|
+
const gcpIap = createAuthProviderIntegration({
|
|
2210
|
+
create(options) {
|
|
2211
|
+
return ({ config, resolverContext }) => {
|
|
2212
|
+
var _a;
|
|
2213
|
+
const audience = config.getString("audience");
|
|
2214
|
+
const authHandler = (_a = options.authHandler) != null ? _a : defaultAuthHandler;
|
|
2215
|
+
const signInResolver = options.signIn.resolver;
|
|
2216
|
+
const tokenValidator = createTokenValidator(audience);
|
|
2217
|
+
return new GcpIapProvider({
|
|
2218
|
+
authHandler,
|
|
2219
|
+
signInResolver,
|
|
2220
|
+
tokenValidator,
|
|
2221
|
+
resolverContext
|
|
2222
|
+
});
|
|
2223
|
+
};
|
|
2224
|
+
}
|
|
2225
|
+
});
|
|
2226
|
+
const createGcpIapProvider = gcpIap.create;
|
|
2227
|
+
|
|
2228
|
+
const providers = Object.freeze({
|
|
2229
|
+
atlassian,
|
|
2230
|
+
auth0,
|
|
2231
|
+
awsAlb,
|
|
2232
|
+
bitbucket,
|
|
2233
|
+
gcpIap,
|
|
2234
|
+
github,
|
|
2235
|
+
gitlab,
|
|
2236
|
+
google,
|
|
2237
|
+
microsoft,
|
|
2238
|
+
oauth2,
|
|
2239
|
+
oauth2Proxy,
|
|
2240
|
+
oidc,
|
|
2241
|
+
okta,
|
|
2242
|
+
onelogin,
|
|
2243
|
+
saml
|
|
2244
|
+
});
|
|
2710
2245
|
|
|
2711
2246
|
const factories = {
|
|
2712
2247
|
google: createGoogleProvider(),
|
|
@@ -2778,10 +2313,10 @@ class TokenFactory {
|
|
|
2778
2313
|
throw new Error('"sub" claim provided by the auth resolver is not a valid EntityRef.');
|
|
2779
2314
|
}
|
|
2780
2315
|
this.logger.info(`Issuing token for ${sub}, with entities ${ent != null ? ent : []}`);
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
});
|
|
2316
|
+
if (!key.alg) {
|
|
2317
|
+
throw new errors.AuthenticationError("No algorithm was provided in the key");
|
|
2318
|
+
}
|
|
2319
|
+
return new jose.SignJWT({ iss, sub, aud, iat, exp }).setProtectedHeader({ alg: key.alg, kid: key.kid }).setIssuer(iss).setAudience(aud).setSubject(sub).setIssuedAt(iat).setExpirationTime(exp).sign(await jose.importJWK(key));
|
|
2785
2320
|
}
|
|
2786
2321
|
async listPublicKeys() {
|
|
2787
2322
|
const { items: keys } = await this.keyStore.listKeys();
|
|
@@ -2818,14 +2353,14 @@ class TokenFactory {
|
|
|
2818
2353
|
seconds: this.keyDurationSeconds
|
|
2819
2354
|
}).toJSDate();
|
|
2820
2355
|
const promise = (async () => {
|
|
2821
|
-
const key = await jose.
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
this.logger.info(`Created new signing key ${
|
|
2827
|
-
await this.keyStore.addKey(
|
|
2828
|
-
return
|
|
2356
|
+
const key = await jose.generateKeyPair("ES256");
|
|
2357
|
+
const publicKey = await jose.exportJWK(key.publicKey);
|
|
2358
|
+
const privateKey = await jose.exportJWK(key.privateKey);
|
|
2359
|
+
publicKey.kid = privateKey.kid = uuid.v4();
|
|
2360
|
+
publicKey.alg = privateKey.alg = "ES256";
|
|
2361
|
+
this.logger.info(`Created new signing key ${publicKey.kid}`);
|
|
2362
|
+
await this.keyStore.addKey(publicKey);
|
|
2363
|
+
return privateKey;
|
|
2829
2364
|
})();
|
|
2830
2365
|
this.privateKeyPromise = promise;
|
|
2831
2366
|
try {
|
|
@@ -2994,6 +2529,149 @@ class KeyStores {
|
|
|
2994
2529
|
}
|
|
2995
2530
|
}
|
|
2996
2531
|
|
|
2532
|
+
class CatalogIdentityClient {
|
|
2533
|
+
constructor(options) {
|
|
2534
|
+
this.catalogApi = options.catalogApi;
|
|
2535
|
+
this.tokenManager = options.tokenManager;
|
|
2536
|
+
}
|
|
2537
|
+
async findUser(query) {
|
|
2538
|
+
const filter = {
|
|
2539
|
+
kind: "user"
|
|
2540
|
+
};
|
|
2541
|
+
for (const [key, value] of Object.entries(query.annotations)) {
|
|
2542
|
+
filter[`metadata.annotations.${key}`] = value;
|
|
2543
|
+
}
|
|
2544
|
+
const { token } = await this.tokenManager.getToken();
|
|
2545
|
+
const { items } = await this.catalogApi.getEntities({ filter }, { token });
|
|
2546
|
+
if (items.length !== 1) {
|
|
2547
|
+
if (items.length > 1) {
|
|
2548
|
+
throw new errors.ConflictError("User lookup resulted in multiple matches");
|
|
2549
|
+
} else {
|
|
2550
|
+
throw new errors.NotFoundError("User not found");
|
|
2551
|
+
}
|
|
2552
|
+
}
|
|
2553
|
+
return items[0];
|
|
2554
|
+
}
|
|
2555
|
+
async resolveCatalogMembership(query) {
|
|
2556
|
+
const { entityRefs, logger } = query;
|
|
2557
|
+
const resolvedEntityRefs = entityRefs.map((ref) => {
|
|
2558
|
+
try {
|
|
2559
|
+
const parsedRef = catalogModel.parseEntityRef(ref.toLocaleLowerCase("en-US"), {
|
|
2560
|
+
defaultKind: "user",
|
|
2561
|
+
defaultNamespace: "default"
|
|
2562
|
+
});
|
|
2563
|
+
return parsedRef;
|
|
2564
|
+
} catch {
|
|
2565
|
+
logger == null ? void 0 : logger.warn(`Failed to parse entityRef from ${ref}, ignoring`);
|
|
2566
|
+
return null;
|
|
2567
|
+
}
|
|
2568
|
+
}).filter((ref) => ref !== null);
|
|
2569
|
+
const filter = resolvedEntityRefs.map((ref) => ({
|
|
2570
|
+
kind: ref.kind,
|
|
2571
|
+
"metadata.namespace": ref.namespace,
|
|
2572
|
+
"metadata.name": ref.name
|
|
2573
|
+
}));
|
|
2574
|
+
const { token } = await this.tokenManager.getToken();
|
|
2575
|
+
const entities = await this.catalogApi.getEntities({ filter }, { token }).then((r) => r.items);
|
|
2576
|
+
if (entityRefs.length !== entities.length) {
|
|
2577
|
+
const foundEntityNames = entities.map(catalogModel.stringifyEntityRef);
|
|
2578
|
+
const missingEntityNames = resolvedEntityRefs.map(catalogModel.stringifyEntityRef).filter((s) => !foundEntityNames.includes(s));
|
|
2579
|
+
logger == null ? void 0 : logger.debug(`Entities not found for refs ${missingEntityNames.join()}`);
|
|
2580
|
+
}
|
|
2581
|
+
const memberOf = entities.flatMap((e) => {
|
|
2582
|
+
var _a, _b;
|
|
2583
|
+
return (_b = (_a = e.relations) == null ? void 0 : _a.filter((r) => r.type === catalogModel.RELATION_MEMBER_OF).map((r) => r.targetRef)) != null ? _b : [];
|
|
2584
|
+
});
|
|
2585
|
+
const newEntityRefs = [
|
|
2586
|
+
...new Set(resolvedEntityRefs.map(catalogModel.stringifyEntityRef).concat(memberOf))
|
|
2587
|
+
];
|
|
2588
|
+
logger == null ? void 0 : logger.debug(`Found catalog membership: ${newEntityRefs.join()}`);
|
|
2589
|
+
return newEntityRefs;
|
|
2590
|
+
}
|
|
2591
|
+
}
|
|
2592
|
+
|
|
2593
|
+
function getEntityClaims(entity) {
|
|
2594
|
+
var _a, _b;
|
|
2595
|
+
const userRef = catalogModel.stringifyEntityRef(entity);
|
|
2596
|
+
const membershipRefs = (_b = (_a = entity.relations) == null ? void 0 : _a.filter((r) => r.type === catalogModel.RELATION_MEMBER_OF && r.targetRef.startsWith("group:")).map((r) => r.targetRef)) != null ? _b : [];
|
|
2597
|
+
return {
|
|
2598
|
+
sub: userRef,
|
|
2599
|
+
ent: [userRef, ...membershipRefs]
|
|
2600
|
+
};
|
|
2601
|
+
}
|
|
2602
|
+
|
|
2603
|
+
function getDefaultOwnershipEntityRefs(entity) {
|
|
2604
|
+
var _a, _b;
|
|
2605
|
+
const membershipRefs = (_b = (_a = entity.relations) == null ? void 0 : _a.filter((r) => r.type === catalogModel.RELATION_MEMBER_OF && r.targetRef.startsWith("group:")).map((r) => r.targetRef)) != null ? _b : [];
|
|
2606
|
+
return Array.from(/* @__PURE__ */ new Set([catalogModel.stringifyEntityRef(entity), ...membershipRefs]));
|
|
2607
|
+
}
|
|
2608
|
+
class CatalogAuthResolverContext {
|
|
2609
|
+
constructor(logger, tokenIssuer, catalogIdentityClient, catalogApi, tokenManager) {
|
|
2610
|
+
this.logger = logger;
|
|
2611
|
+
this.tokenIssuer = tokenIssuer;
|
|
2612
|
+
this.catalogIdentityClient = catalogIdentityClient;
|
|
2613
|
+
this.catalogApi = catalogApi;
|
|
2614
|
+
this.tokenManager = tokenManager;
|
|
2615
|
+
}
|
|
2616
|
+
static create(options) {
|
|
2617
|
+
const catalogIdentityClient = new CatalogIdentityClient({
|
|
2618
|
+
catalogApi: options.catalogApi,
|
|
2619
|
+
tokenManager: options.tokenManager
|
|
2620
|
+
});
|
|
2621
|
+
return new CatalogAuthResolverContext(options.logger, options.tokenIssuer, catalogIdentityClient, options.catalogApi, options.tokenManager);
|
|
2622
|
+
}
|
|
2623
|
+
async issueToken(params) {
|
|
2624
|
+
const token = await this.tokenIssuer.issueToken(params);
|
|
2625
|
+
return { token };
|
|
2626
|
+
}
|
|
2627
|
+
async findCatalogUser(query) {
|
|
2628
|
+
let result = void 0;
|
|
2629
|
+
const { token } = await this.tokenManager.getToken();
|
|
2630
|
+
if ("entityRef" in query) {
|
|
2631
|
+
const entityRef = catalogModel.parseEntityRef(query.entityRef, {
|
|
2632
|
+
defaultKind: "User",
|
|
2633
|
+
defaultNamespace: catalogModel.DEFAULT_NAMESPACE
|
|
2634
|
+
});
|
|
2635
|
+
result = await this.catalogApi.getEntityByRef(entityRef, { token });
|
|
2636
|
+
} else if ("annotations" in query) {
|
|
2637
|
+
const filter = {
|
|
2638
|
+
kind: "user"
|
|
2639
|
+
};
|
|
2640
|
+
for (const [key, value] of Object.entries(query.annotations)) {
|
|
2641
|
+
filter[`metadata.annotations.${key}`] = value;
|
|
2642
|
+
}
|
|
2643
|
+
const res = await this.catalogApi.getEntities({ filter }, { token });
|
|
2644
|
+
result = res.items;
|
|
2645
|
+
} else if ("filter" in query) {
|
|
2646
|
+
const res = await this.catalogApi.getEntities({ filter: query.filter }, { token });
|
|
2647
|
+
result = res.items;
|
|
2648
|
+
} else {
|
|
2649
|
+
throw new errors.InputError("Invalid user lookup query");
|
|
2650
|
+
}
|
|
2651
|
+
if (Array.isArray(result)) {
|
|
2652
|
+
if (result.length > 1) {
|
|
2653
|
+
throw new errors.ConflictError("User lookup resulted in multiple matches");
|
|
2654
|
+
}
|
|
2655
|
+
result = result[0];
|
|
2656
|
+
}
|
|
2657
|
+
if (!result) {
|
|
2658
|
+
throw new errors.NotFoundError("User not found");
|
|
2659
|
+
}
|
|
2660
|
+
return { entity: result };
|
|
2661
|
+
}
|
|
2662
|
+
async signInWithCatalogUser(query) {
|
|
2663
|
+
const { entity } = await this.findCatalogUser(query);
|
|
2664
|
+
const ownershipRefs = getDefaultOwnershipEntityRefs(entity);
|
|
2665
|
+
const token = await this.tokenIssuer.issueToken({
|
|
2666
|
+
claims: {
|
|
2667
|
+
sub: catalogModel.stringifyEntityRef(entity),
|
|
2668
|
+
ent: ownershipRefs
|
|
2669
|
+
}
|
|
2670
|
+
});
|
|
2671
|
+
return { token };
|
|
2672
|
+
}
|
|
2673
|
+
}
|
|
2674
|
+
|
|
2997
2675
|
async function createRouter(options) {
|
|
2998
2676
|
const {
|
|
2999
2677
|
logger,
|
|
@@ -3055,7 +2733,13 @@ async function createRouter(options) {
|
|
|
3055
2733
|
tokenManager,
|
|
3056
2734
|
tokenIssuer,
|
|
3057
2735
|
discovery,
|
|
3058
|
-
catalogApi
|
|
2736
|
+
catalogApi,
|
|
2737
|
+
resolverContext: CatalogAuthResolverContext.create({
|
|
2738
|
+
logger,
|
|
2739
|
+
catalogApi,
|
|
2740
|
+
tokenIssuer,
|
|
2741
|
+
tokenManager
|
|
2742
|
+
})
|
|
3059
2743
|
});
|
|
3060
2744
|
const r = Router__default["default"]();
|
|
3061
2745
|
r.get("/start", provider.start.bind(provider));
|
|
@@ -3133,12 +2817,15 @@ exports.createSamlProvider = createSamlProvider;
|
|
|
3133
2817
|
exports.defaultAuthProviderFactories = factories;
|
|
3134
2818
|
exports.encodeState = encodeState;
|
|
3135
2819
|
exports.ensuresXRequestedWith = ensuresXRequestedWith;
|
|
2820
|
+
exports.getDefaultOwnershipEntityRefs = getDefaultOwnershipEntityRefs;
|
|
3136
2821
|
exports.getEntityClaims = getEntityClaims;
|
|
3137
2822
|
exports.googleEmailSignInResolver = googleEmailSignInResolver;
|
|
3138
2823
|
exports.microsoftEmailSignInResolver = microsoftEmailSignInResolver;
|
|
3139
2824
|
exports.oktaEmailSignInResolver = oktaEmailSignInResolver;
|
|
3140
2825
|
exports.postMessageResponse = postMessageResponse;
|
|
3141
2826
|
exports.prepareBackstageIdentityResponse = prepareBackstageIdentityResponse;
|
|
2827
|
+
exports.providers = providers;
|
|
3142
2828
|
exports.readState = readState;
|
|
2829
|
+
exports.samlNameIdEntityNameSignInResolver = samlNameIdEntityNameSignInResolver;
|
|
3143
2830
|
exports.verifyNonce = verifyNonce;
|
|
3144
2831
|
//# sourceMappingURL=index.cjs.js.map
|