@milaboratories/pl-client 3.15.0 → 3.16.1
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/dist/core/capabilities.cjs.map +1 -1
- package/dist/core/capabilities.d.ts +1 -1
- package/dist/core/capabilities.d.ts.map +1 -1
- package/dist/core/capabilities.js.map +1 -1
- package/dist/core/ll_client.cjs +35 -18
- package/dist/core/ll_client.cjs.map +1 -1
- package/dist/core/ll_client.d.ts +12 -5
- package/dist/core/ll_client.d.ts.map +1 -1
- package/dist/core/ll_client.js +35 -18
- package/dist/core/ll_client.js.map +1 -1
- package/dist/core/transaction.cjs +2 -1
- package/dist/core/transaction.cjs.map +1 -1
- package/dist/core/transaction.d.ts.map +1 -1
- package/dist/core/transaction.js +2 -1
- package/dist/core/transaction.js.map +1 -1
- package/dist/core/unauth_client.cjs +79 -32
- package/dist/core/unauth_client.cjs.map +1 -1
- package/dist/core/unauth_client.d.ts +49 -14
- package/dist/core/unauth_client.d.ts.map +1 -1
- package/dist/core/unauth_client.js +79 -32
- package/dist/core/unauth_client.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.cjs +150 -18
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.cjs.map +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.d.ts +127 -9
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.d.ts.map +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.js +150 -18
- package/dist/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.js.map +1 -1
- package/dist/proto-rest/plapi.d.ts +8 -2
- package/dist/proto-rest/plapi.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/core/capabilities.ts +4 -0
- package/src/core/ll_client.ts +25 -13
- package/src/core/transaction.ts +2 -0
- package/src/core/unauth_client.test.ts +69 -1
- package/src/core/unauth_client.ts +108 -34
- package/src/core/unauth_client_branch.test.ts +416 -5
- package/src/proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.ts +225 -15
- package/src/proto-rest/plapi.ts +8 -2
|
@@ -585,7 +585,9 @@ export interface components {
|
|
|
585
585
|
*/
|
|
586
586
|
clientSecret: string;
|
|
587
587
|
};
|
|
588
|
-
AuthAPI_BeginSSOLogin_Request:
|
|
588
|
+
AuthAPI_BeginSSOLogin_Request: {
|
|
589
|
+
idp: string;
|
|
590
|
+
};
|
|
589
591
|
AuthAPI_BeginSSOLogin_Response: {
|
|
590
592
|
publicPkce: components["schemas"]["AuthAPI_BeginSSOLogin_PublicPKCE"];
|
|
591
593
|
};
|
|
@@ -639,8 +641,10 @@ export interface components {
|
|
|
639
641
|
* instance. Unique across the entire server.
|
|
640
642
|
*/
|
|
641
643
|
id: string;
|
|
642
|
-
/** @description description is the human-readable
|
|
644
|
+
/** @description description is the long-form human-readable text a client may render alongside the title, for example in a tooltip or under the button. */
|
|
643
645
|
description: string;
|
|
646
|
+
/** @description title is the short human-readable label a client renders for this method, for example on the sign-in button. Always set. */
|
|
647
|
+
title: string;
|
|
644
648
|
basic: components["schemas"]["AuthAPI_ListMethods_BasicAuthMethod"];
|
|
645
649
|
token: components["schemas"]["AuthAPI_ListMethods_TokenAuthMethod"];
|
|
646
650
|
sso: components["schemas"]["AuthAPI_ListMethods_SSOAuthMethod"];
|
|
@@ -671,6 +675,7 @@ export interface components {
|
|
|
671
675
|
AuthAPI_Login_BasicCredentials: {
|
|
672
676
|
login: string;
|
|
673
677
|
password: string;
|
|
678
|
+
idp: string;
|
|
674
679
|
};
|
|
675
680
|
AuthAPI_Login_Request: {
|
|
676
681
|
basic: components["schemas"]["AuthAPI_Login_BasicCredentials"];
|
|
@@ -694,6 +699,7 @@ export interface components {
|
|
|
694
699
|
AuthAPI_Login_SSOCredentials: {
|
|
695
700
|
/** Format: bytes */
|
|
696
701
|
tokenResponse: string;
|
|
702
|
+
idp: string;
|
|
697
703
|
};
|
|
698
704
|
/**
|
|
699
705
|
* @description TokenCredentials accepts any opaque bearer-style string: a controller
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plapi.d.ts","names":[],"sources":["../../src/proto-rest/plapi.ts"],"mappings":";;;;;iBAKiB;EACf;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;IACA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;;;;;;IAMA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;;;;;;IAMA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;;IAGF,KAAK;IACL;IACA;IACA;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;;;;;;IAMA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;;;;;;;IAOA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;IACA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;IACA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;;;;;;IAMA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;IACA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;IACA,MAAM;IACN,QAAQ;IACR;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;IACA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;IACA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;IACA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;IACA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;IACA,MAAM;IACN,QAAQ;IACR;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;IACA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;IACA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;;IAEA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;IACA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;IACA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF,KAAK;IACL;IACA;IACA;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;;;;;;IAMA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;IACA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;IACA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;;;;;;;;;;;;;;;;;IAiBA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;IACA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;;IAGF,KAAK;IACL;IACA;IACA;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;;IAGF,KAAK;IACL;IACA;IACA;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;;IAEA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;IACA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;IACA,MAAM;IACN;IACA;IACA;IACA;IACA;;;iBAIa;EACf;IACE;MACE;;MAEA;;;;;;;;;MASA;;IAEF
|
|
1
|
+
{"version":3,"file":"plapi.d.ts","names":[],"sources":["../../src/proto-rest/plapi.ts"],"mappings":";;;;;iBAKiB;EACf;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;IACA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;;;;;;IAMA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;;;;;;IAMA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;;IAGF,KAAK;IACL;IACA;IACA;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;;;;;;IAMA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;;;;;;;IAOA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;IACA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;IACA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;;;;;;IAMA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;IACA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;IACA,MAAM;IACN,QAAQ;IACR;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;IACA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;IACA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;IACA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;IACA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;IACA,MAAM;IACN,QAAQ;IACR;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;IACA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;IACA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;;IAEA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;IACA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;IACA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF,KAAK;IACL;IACA;IACA;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;;;;;;IAMA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;IACA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;IACA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;;;;;;;;;;;;;;;;;IAiBA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;IACA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;;IAGF,KAAK;IACL;IACA;IACA;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;;IAGF,KAAK;IACL;IACA;IACA;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;;IAEA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;IACA,MAAM;IACN;IACA;IACA;IACA;IACA;;EAEF;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;IACA,MAAM;IACN;IACA;IACA;IACA;IACA;;;iBAIa;EACf;IACE;MACE;;MAEA;;;;;;;;;MASA;;IAEF;MACE;;IAEF;MACE,YAAY;;IAEd;MACE;;MAEA;;IAEF;MACE;;;;;MAKA;;MAEA;;IAEF,gCAAgC;IAChC;;MAEE;;MAEA;;IAEF;MACE;MACA;;IAEF;MACE,UAAU;;IAEZ;MACE;;MAEA;MACA;MACA,aAAa;;MAEb;;IAEF,8BAA8B;;IAE9B;MACE;;IAEF,qCAAqC;IACrC;;;;;MAKE;;MAEA;;MAEA;MACA,OAAO;MACP,OAAO;MACP,KAAK;;IAEP;MACE,SAAS;;;;;;;IAOX;MACE;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;;MAEA;MACA;;IAEF,qCAAqC;IACrC;MACE;MACA;MACA;;IAEF;MACE,OAAO;MACP,OAAO;MACP,KAAK;MACL;;MAEA;;IAEF;MACE;;MAEA;;MAEA;;;;;;IAMF;;MAEE;MACA;;;;;;IAMF;;MAEE;;IAEF;MACE;;MAEA;MACA,OAAO;;IAET;MACE;;MAEA;;IAEF;MACE;MACA;;IAEF;MACE;;MAEA;;MAEA;;IAEF;MACE;;MAEA;MACA;;IAEF,+BAA+B;IAC/B;MACE;;MAEA;;IAEF;MACE;;MAEA;;IAEF;MACE;MACA;MACA;;IAEF;MACE;MACA;;IAEF,2CAA2C;IAC3C;MACE;;IAEF,sCAAsC;IACtC;MACE;MACA;;IAEF;MACE;;IAEF;MACE;;IAEF,mCAAmC;IACnC;MACE;;IAEF;MACE;;IAEF;MACE;;MAEA;;IAEF;MACE,eAAe;;IAEjB;MACE;MACA;;IAEF;MACE;;IAEF;MACE;;IAEF;MACE,YAAY;;IAEd;MACE;MACA;SACG,cAAc;;MAEjB,iBAAiB;;IAEnB;MACE;MACA;;IAEF;MACE;;IAEF,6CAA6C;IAC7C;MACE,UAAU;;IAEZ,oCAAoC;IACpC;MACE;MACA;SACG,cAAc;;MAEjB,iBAAiB;;IAEnB,+BAA+B;IAC/B;MACE;MACA;SACG;;;IAGL,4CAA4C;IAC5C;;MAEE,IAAI;;MAEJ;MACA,UAAU;;;;;;;;MAQV;;;;;;MAMA;;;;;MAKA;;MAEA;;;;;MAKA;;;;;MAKA;;IAEF;MACE;;MAEA;MACA;;IAEF;;MAEE;MACA;;;IAGF;;MAEE;;OAEC;;IAEH;MACE;;MAEA;MACA;MACA;;IAEF;;MAEE;;IAEF;MACE;;MAEA;;MAEA;;IAEF,iCAAiC;IACjC;MACE;;MAEA;;MAEA;MACA;MACA;;IAEF,gCAAgC;IAChC;MACE;MACA;MACA;;IAEF;;;;;MAKE;;;;;;MAMA,kBAAkB;MAClB;;IAEF;MACE;MACA;MACA;;MAEA;MACA;;IAEF;;MAEE;MACA;;;;;MAKA;;IAEF;MACE;MACA;;MAEA;;;;;;;MAOA;MACA;MACA;MACA;;;;;;;;;;;;;;;;;;;MAmBA;;IAEF;MACE,OAAO;;IAET;MACE;MACA;MACA;MACA,cAAc;MACd,QAAQ;MACR;SACG,cAAc;;MAEjB,SAAS;MACT;MACA,QAAQ;;IAEV;MACE;;MAEA;;IAEF;MACE,eAAe;;IAEjB;MACE,cAAc;MACd;MACA,aAAa;MACb,SAAS;;IAEX;MACE;MACA;MACA;MACA;MACA;MACA;MACA;;MAEA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;;IAEF;MACE;SACG;;;IAGL;MACE;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;;IAEF;MACE,KAAK;MACL,KAAK;;IAEP;MACE;MACA;MACA,cAAc;MACd;;IAEF;MACE,MAAM;MACN,QAAQ;;MAER,aAAa;MACb;MACA;;IAEF;;;;;MAKE;;MAEA;MACA;;MAEA;MACA;;;;;MAKA;SACG;;MAEH;SACG;;;;;;MAMH;;IAEF;MACE;MACA;;IAEF;MACE;;IAEF;MACE;MACA;SACG;;;;IAIL;;;;;MAKE;;MAEA;;MAEA,SAAS;;IAEX;MACE;MACA;MACA;;IAEF,uCAAuC;IACvC;MACE;MACA;;IAEF,uCAAuC;IACvC;MACE;;IAEF,qBAAqB;;EAEvB;EACA;EACA;EACA;EACA;;iBAGe;EACf;IACE;MACE;MACA;MACA;MACA;;IAEF;MACE;QACE,oBAAoB;;;IAGxB;;MAEE;QACE;WACG;;QAEH;UACE,oBAAoB;;;;MAIxB;QACE;WACG;;QAEH;UACE,oBAAoB;;;;;EAK5B;IACE;MACE;MACA;MACA;MACA;;IAEF;MACE;QACE,oBAAoB;;;IAGxB;;MAEE;QACE;WACG;;QAEH;UACE,oBAAoB;;;;MAIxB;QACE;WACG;;QAEH;UACE,oBAAoB;;;;;EAK5B;IACE;MACE;MACA;MACA;MACA;;IAEF;MACE;QACE,oBAAoB;;;IAGxB;;MAEE;QACE;WACG;;QAEH;UACE,oBAAoB;;;;MAIxB;QACE;WACG;;QAEH;UACE,oBAAoB;;;;;EAK5B;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;;MAEE;QACE;WACG;;QAEH;UACE,oBAAoB;;;;MAIxB;QACE;WACG;;QAEH;UACE,oBAAoB;;;;;EAK5B;IACE;MACE;MACA;MACA;MACA;;IAEF;MACE;QACE,oBAAoB;;;IAGxB;;MAEE;QACE;WACG;;QAEH;UACE,oBAAoB;;;;MAIxB;QACE;WACG;;QAEH;UACE,oBAAoB;;;;;EAK5B;IACE;MACE;MACA;MACA;MACA;;IAEF;MACE;QACE,oBAAoB;;;IAGxB;;MAEE;QACE;WACG;;QAEH;UACE,oBAAoB;;;;MAIxB;QACE;WACG;;QAEH;UACE,oBAAoB;;;;;EAK5B;IACE;MACE;MACA;MACA;MACA;;IAEF;MACE;QACE,oBAAoB;;;IAGxB;;MAEE;QACE;WACG;;QAEH;UACE,oBAAoB;;;;MAIxB;QACE;WACG;;QAEH;UACE,oBAAoB;;;;;EAK5B;IACE;MACE;MACA;MACA;MACA;;IAEF;MACE;QACE,oBAAoB;;;IAGxB;;MAEE;QACE;WACG;;QAEH;UACE,oBAAoB;;;;MAIxB;QACE;WACG;;QAEH;UACE,oBAAoB;;;;;EAK5B;IACE;MACE;MACA;MACA;MACA;;IAEF;MACE;QACE,oBAAoB;;;IAGxB;;MAEE;QACE;WACG;;QAEH;UACE,oBAAoB;;;;MAIxB;QACE;WACG;;QAEH;UACE,oBAAoB;;;;;EAK5B;IACE;MACE;MACA;MACA;MACA;;IAEF;MACE;QACE,oBAAoB;;;IAGxB;;MAEE;QACE;WACG;;QAEH;UACE,oBAAoB;;;;MAIxB;QACE;WACG;;QAEH;UACE,oBAAoB;;;;;EAK5B;IACE;MACE;MACA;MACA;MACA;;IAEF;MACE;QACE,oBAAoB;;;IAGxB;;MAEE;QACE;WACG;;QAEH;UACE,oBAAoB;;;;MAIxB;QACE;WACG;;QAEH;UACE,oBAAoB;;;;;EAK5B;IACE;MACE;MACA;MACA;MACA;;IAEF;MACE;QACE,oBAAoB;;;IAGxB;;MAEE;QACE;WACG;;QAEH;UACE,oBAAoB;;;;MAIxB;QACE;WACG;;QAEH;UACE,oBAAoB;;;;;EAK5B;IACE;MACE;MACA;MACA;MACA;;IAEF;MACE;QACE,oBAAoB;;;IAGxB;;MAEE;QACE;WACG;;QAEH;UACE,oBAAoB;;;;MAIxB;QACE;WACG;;QAEH;UACE,oBAAoB;;;;;EAK5B;IACE;MACE;MACA;MACA;MACA;;IAEF;MACE;QACE,oBAAoB;;;IAGxB;;MAEE;QACE;WACG;;QAEH;UACE,oBAAoB;;;;MAIxB;QACE;WACG;;QAEH;UACE,oBAAoB;;;;;EAK5B;IACE;MACE;MACA;MACA;MACA;;IAEF;MACE;QACE,oBAAoB;;;IAGxB;;MAEE;QACE;WACG;;QAEH;UACE,oBAAoB;;;;MAIxB;QACE;WACG;;QAEH;UACE,oBAAoB;;;;;EAK5B;IACE;MACE;MACA;MACA;MACA;;IAEF;MACE;QACE,oBAAoB;;;IAGxB;;MAEE;QACE;WACG;;QAEH;UACE,oBAAoB;;;;MAIxB;QACE;WACG;;QAEH;UACE,oBAAoB;;;;;EAK5B;IACE;MACE;MACA;MACA;MACA;;IAEF;MACE;QACE,oBAAoB;;;IAGxB;;MAEE;QACE;WACG;;QAEH;UACE,oBAAoB;;;;MAIxB;QACE;WACG;;QAEH;UACE,oBAAoB;;;;;EAK5B;IACE;MACE;MACA;MACA;MACA;;IAEF;MACE;QACE,oBAAoB;;;IAGxB;;MAEE;QACE;WACG;;QAEH;UACE,oBAAoB;;;;MAIxB;QACE;WACG;;QAEH;UACE,oBAAoB;;;;;EAK5B;IACE;MACE;MACA;MACA;MACA;;IAEF;MACE;QACE,oBAAoB;;;IAGxB;;MAEE;QACE;WACG;;QAEH;UACE,oBAAoB;;;;MAIxB;QACE;WACG;;QAEH;UACE,oBAAoB;;;;;EAK5B;IACE;MACE;MACA;MACA;MACA;;IAEF;MACE;QACE,oBAAoB;;;IAGxB;;MAEE;QACE;WACG;;QAEH;UACE,oBAAoB;;;;MAIxB;QACE;WACG;;QAEH;UACE,oBAAoB;;;;;EAK5B;IACE;MACE;MACA;MACA;MACA;;IAEF;MACE;QACE,oBAAoB;;;IAGxB;;MAEE;QACE;WACG;;QAEH;UACE,oBAAoB;;;;MAIxB;QACE;WACG;;QAEH;UACE,oBAAoB;;;;;EAK5B;IACE;MACE;MACA;MACA;MACA;;IAEF;MACE;QACE,oBAAoB;;;IAGxB;;MAEE;QACE;WACG;;QAEH;UACE,oBAAoB;;;;MAIxB;QACE;WACG;;QAEH;UACE,oBAAoB;;;;;EAK5B;IACE;MACE;MACA;MACA;MACA;;IAEF;MACE;QACE,oBAAoB;;;IAGxB;;MAEE;QACE;WACG;;QAEH;UACE,oBAAoB;;;;MAIxB;QACE;WACG;;QAEH;UACE,oBAAoB;;;;;EAK5B;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;;MAEE;QACE;WACG;;QAEH;UACE,oBAAoB;;;;MAIxB;QACE;WACG;;QAEH;UACE,oBAAoB;;;;;EAK5B;IACE;MACE;MACA;MACA;MACA;;IAEF;MACE;QACE,oBAAoB;;;IAGxB;;MAEE;QACE;WACG;;QAEH;UACE,oBAAoB;;;;MAIxB;QACE;WACG;;QAEH;UACE,oBAAoB;;;;;EAK5B;IACE;MACE;MACA;MACA;MACA;;IAEF;MACE;QACE,oBAAoB;;;IAGxB;;MAEE;QACE;WACG;;QAEH;UACE,oBAAoB;;;;MAIxB;QACE;WACG;;QAEH;UACE,oBAAoB;;;;;EAK5B;IACE;MACE;MACA;MACA;MACA;;IAEF;MACE;QACE,oBAAoB;;;IAGxB;;MAEE;QACE;WACG;;QAEH;UACE,oBAAoB;;;;MAIxB;QACE;WACG;;QAEH;UACE,oBAAoB;;;;;EAK5B;IACE;MACE;MACA;MACA;MACA;;IAEF;MACE;QACE,oBAAoB;;;IAGxB;;MAEE;QACE;WACG;;QAEH;UACE,oBAAoB;;;;MAIxB;QACE;WACG;;QAEH;UACE,oBAAoB;;;;;EAK5B;IACE;MACE;MACA;MACA;MACA;;IAEF;MACE;QACE,oBAAoB;;;IAGxB;;MAEE;QACE;WACG;;QAEH;UACE,oBAAoB;;;;MAIxB;QACE;WACG;;QAEH;UACE,oBAAoB;;;;;EAK5B;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;;MAEE;QACE;WACG;;QAEH;UACE,oBAAoB;;;;MAIxB;QACE;WACG;;QAEH;UACE,oBAAoB;;;;;EAK5B;IACE;MACE;MACA;MACA;MACA;;IAEF;IACA;;MAEE;QACE;WACG;;QAEH;UACE,oBAAoB;;;;MAIxB;QACE;WACG;;QAEH;UACE,oBAAoB;;;;;EAK5B;IACE;MACE;MACA;MACA;MACA;;IAEF;MACE;QACE,oBAAoB;;;IAGxB;;MAEE;QACE;WACG;;QAEH;UACE,oBAAoB;;;;MAIxB;QACE;WACG;;QAEH;UACE,oBAAoB;;;;;EAK5B;IACE;MACE;MACA;MACA;MACA;;IAEF;MACE;QACE,oBAAoB;;;IAGxB;;MAEE;QACE;WACG;;QAEH;UACE,oBAAoB;;;;MAIxB;QACE;WACG;;QAEH;UACE,oBAAoB;;;;;EAK5B;IACE;MACE;MACA;MACA;MACA;;IAEF;MACE;QACE,oBAAoB;;;IAGxB;;MAEE;QACE;WACG;;QAEH;UACE,oBAAoB;;;;MAIxB;QACE;WACG;;QAEH;UACE,oBAAoB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@milaboratories/pl-client",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.16.1",
|
|
4
4
|
"description": "New TS/JS client for Platform API",
|
|
5
5
|
"files": [
|
|
6
6
|
"./dist/**/*",
|
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
"utility-types": "^3.11.0",
|
|
32
32
|
"yaml": "^2.8.0",
|
|
33
33
|
"@milaboratories/pl-model-common": "1.48.0",
|
|
34
|
-
"@milaboratories/
|
|
35
|
-
"@milaboratories/
|
|
34
|
+
"@milaboratories/ts-helpers": "1.8.6",
|
|
35
|
+
"@milaboratories/pl-http": "1.2.4"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@protobuf-ts/plugin": "2.11.1",
|
package/src/core/capabilities.ts
CHANGED
|
@@ -18,6 +18,10 @@ export type BackendCapability =
|
|
|
18
18
|
| "auth:v2"
|
|
19
19
|
| "treeFilter:v2"
|
|
20
20
|
| "wasm:v1"
|
|
21
|
+
// Advertised only where the deployment actually has scratch storage, not merely where the
|
|
22
|
+
// build understands a 'scratchFreeSpace' request: a client that sees this stops arranging
|
|
23
|
+
// its own temporary storage. Off unless pl was started with --has-scratch-space.
|
|
24
|
+
| "scratchSpace:v1"
|
|
21
25
|
// Project-sharing capability tokens.
|
|
22
26
|
| "crossTreeRefs:v1" // cross-color field attach (accept a foreign-colored shared envelope)
|
|
23
27
|
| "userListing:v1" // list users for the recipient picker
|
package/src/core/ll_client.ts
CHANGED
|
@@ -645,15 +645,19 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
645
645
|
}
|
|
646
646
|
}
|
|
647
647
|
|
|
648
|
-
/** Login via username/password. Returns a fresh JWT. Backend creates a new session per call.
|
|
648
|
+
/** Login via username/password. Returns a fresh JWT. Backend creates a new session per call.
|
|
649
|
+
* `opts.idP` names the advertised login method to route to; omitted, the backend keeps its
|
|
650
|
+
* current first-match behaviour. */
|
|
649
651
|
public async loginBasic(
|
|
650
652
|
user: string,
|
|
651
653
|
password: string,
|
|
652
|
-
opts: { ttlSeconds?: bigint; role?: AuthAPI_Role } = {},
|
|
654
|
+
opts: { ttlSeconds?: bigint; role?: AuthAPI_Role; idP?: string } = {},
|
|
653
655
|
): Promise<string> {
|
|
654
656
|
const cl = this.clientProvider.get();
|
|
655
657
|
const ttl = opts.ttlSeconds ?? BigInt(this.conf.authTTLSeconds);
|
|
656
658
|
const role = opts.role ?? AuthAPI_Role.UNSPECIFIED;
|
|
659
|
+
const basic =
|
|
660
|
+
opts.idP === undefined ? { login: user, password } : { login: user, password, idp: opts.idP };
|
|
657
661
|
|
|
658
662
|
if (cl instanceof GrpcPlApiClient) {
|
|
659
663
|
return (
|
|
@@ -661,7 +665,7 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
661
665
|
{
|
|
662
666
|
credentials: {
|
|
663
667
|
oneofKind: "basic",
|
|
664
|
-
basic
|
|
668
|
+
basic,
|
|
665
669
|
},
|
|
666
670
|
expiration: { seconds: ttl, nanos: 0 },
|
|
667
671
|
requestedRole: role,
|
|
@@ -674,7 +678,7 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
674
678
|
// openapi-typescript generated all body fields as required, but Login.Request
|
|
675
679
|
// has a credentials oneof — only one of `basic`/`token` is sent. Cast around it.
|
|
676
680
|
body: {
|
|
677
|
-
basic
|
|
681
|
+
basic,
|
|
678
682
|
expiration: `${ttl}s`,
|
|
679
683
|
requestedRole: role,
|
|
680
684
|
} as any,
|
|
@@ -723,16 +727,19 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
723
727
|
}
|
|
724
728
|
|
|
725
729
|
/** Login via SSO: forwards the raw IdP /token JSON body to the backend.
|
|
726
|
-
* Backend validates signature + nonce + audience and mints a Platforma JWT.
|
|
727
|
-
|
|
730
|
+
* Backend validates signature + nonce + audience and mints a Platforma JWT. `idP` names the
|
|
731
|
+
* advertised login method to route to; omitted, the backend keeps its current first-match
|
|
732
|
+
* behaviour. */
|
|
733
|
+
public async loginSSO(tokenResponse: Uint8Array, idP?: string): Promise<string> {
|
|
728
734
|
const cl = this.clientProvider.get();
|
|
735
|
+
const sso = idP === undefined ? { tokenResponse } : { tokenResponse, idp: idP };
|
|
729
736
|
if (cl instanceof GrpcPlApiClient) {
|
|
730
737
|
return (
|
|
731
738
|
await cl.login(
|
|
732
739
|
{
|
|
733
740
|
credentials: {
|
|
734
741
|
oneofKind: "sso",
|
|
735
|
-
sso
|
|
742
|
+
sso,
|
|
736
743
|
},
|
|
737
744
|
},
|
|
738
745
|
{ timeout: DEFAULT_LOGIN_TIMEOUT },
|
|
@@ -741,7 +748,7 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
741
748
|
} else {
|
|
742
749
|
const resp = cl.POST("/v1/auth/login", {
|
|
743
750
|
body: {
|
|
744
|
-
sso: { tokenResponse: Buffer.from(tokenResponse).toString("base64") },
|
|
751
|
+
sso: { ...sso, tokenResponse: Buffer.from(tokenResponse).toString("base64") },
|
|
745
752
|
} as any,
|
|
746
753
|
});
|
|
747
754
|
return notEmpty((await resp).data, "REST: empty response for SSO login request").token;
|
|
@@ -750,11 +757,16 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
750
757
|
|
|
751
758
|
/** Request a one-time PKCE nonce + its expiry from the backend. The desktop is
|
|
752
759
|
* expected to place the nonce verbatim into the OIDC auth-request before
|
|
753
|
-
* redirecting to the IdP; the backend enforces the expiry on {@link loginSSO}.
|
|
754
|
-
|
|
760
|
+
* redirecting to the IdP; the backend enforces the expiry on {@link loginSSO}. `idP` names the
|
|
761
|
+
* advertised login method to route to; omitted, the backend keeps its current first-match
|
|
762
|
+
* behaviour. */
|
|
763
|
+
public async beginSSOLogin(
|
|
764
|
+
idP?: string,
|
|
765
|
+
): Promise<{ nonce: string; expiresAt: Date; clientSecret?: string }> {
|
|
755
766
|
const cl = this.clientProvider.get();
|
|
767
|
+
const request = idP === undefined ? {} : { idp: idP };
|
|
756
768
|
if (cl instanceof GrpcPlApiClient) {
|
|
757
|
-
const resp = (await cl.beginSSOLogin(
|
|
769
|
+
const resp = (await cl.beginSSOLogin(request).response).flow;
|
|
758
770
|
if (resp.oneofKind !== "publicPkce") {
|
|
759
771
|
throw new Error(`beginSSOLogin: unsupported flow ${resp.oneofKind}`);
|
|
760
772
|
}
|
|
@@ -766,7 +778,7 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
766
778
|
};
|
|
767
779
|
} else {
|
|
768
780
|
const wsResponse = notEmpty(
|
|
769
|
-
(await cl.POST("/v1/auth/sso/begin-login", { body:
|
|
781
|
+
(await cl.POST("/v1/auth/sso/begin-login", { body: request as any })).data,
|
|
770
782
|
"REST: empty response for beginSSOLogin request",
|
|
771
783
|
);
|
|
772
784
|
const pkce = notEmpty(wsResponse.publicPkce, "REST: missing publicPkce in beginSSOLogin");
|
|
@@ -955,7 +967,7 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
955
967
|
// while protobuf-ts models it as a discriminated union. Reshape per item.
|
|
956
968
|
resp = {
|
|
957
969
|
methods: (wsResponse.methods ?? []).map((m): grpcTypes.AuthAPI_ListMethods_MethodInfo => {
|
|
958
|
-
const base = { id: m.id, description: m.description };
|
|
970
|
+
const base = { id: m.id, description: m.description, title: m.title };
|
|
959
971
|
if (m.basic !== undefined) {
|
|
960
972
|
return { ...base, method: { oneofKind: "basic", basic: m.basic } };
|
|
961
973
|
}
|
package/src/core/transaction.ts
CHANGED
|
@@ -1238,6 +1238,8 @@ export class PlTransaction {
|
|
|
1238
1238
|
includeKv: opts?.includeKv ?? false,
|
|
1239
1239
|
maxDepth: opts?.maxDepth,
|
|
1240
1240
|
showSoftDeletes: false,
|
|
1241
|
+
// Empty token requests the full tree — this call has no continuation to resume.
|
|
1242
|
+
changedSinceToken: new Uint8Array(0),
|
|
1241
1243
|
},
|
|
1242
1244
|
});
|
|
1243
1245
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { UnauthenticatedPlClient } from "./unauth_client";
|
|
2
2
|
import { getTestConfig, plAddressToTestConfig } from "../test/test_config";
|
|
3
|
-
import { UnauthenticatedError } from "./errors";
|
|
3
|
+
import { UnauthenticatedError, isUnimplementedError } from "./errors";
|
|
4
4
|
import { test, expect } from "vitest";
|
|
5
5
|
|
|
6
6
|
test("ping test", async () => {
|
|
@@ -30,3 +30,71 @@ test("wrong login", async () => {
|
|
|
30
30
|
UnauthenticatedError,
|
|
31
31
|
);
|
|
32
32
|
});
|
|
33
|
+
|
|
34
|
+
// --- multi-method login ---
|
|
35
|
+
//
|
|
36
|
+
// These cases assume the backend is configured with (at least) two htpasswd
|
|
37
|
+
// login methods whose config `name` values differ but which both accept the
|
|
38
|
+
// same PL_TEST_USER/PL_TEST_PASSWORD credentials — the id
|
|
39
|
+
// is the only thing distinguishing them.
|
|
40
|
+
|
|
41
|
+
/** Runs every multi-method case against one client, gRPC or REST alike. */
|
|
42
|
+
async function runMultiMethodCases(address: string) {
|
|
43
|
+
const testConfig = getTestConfig();
|
|
44
|
+
if (testConfig.test_user === undefined || testConfig.test_password === undefined) {
|
|
45
|
+
console.log("skipped");
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const client = await UnauthenticatedPlClient.build(plAddressToTestConfig(address));
|
|
49
|
+
|
|
50
|
+
const basicMethods = client.loginMethods().filter((m) => m.kind === "basic");
|
|
51
|
+
expect(basicMethods.length).toBeGreaterThanOrEqual(2);
|
|
52
|
+
// The driver's fixed description is the same string on every htpasswd method — only
|
|
53
|
+
// the id tells the two apart.
|
|
54
|
+
expect(basicMethods[0].description).toBe(basicMethods[1].description);
|
|
55
|
+
expect(basicMethods[0].id).not.toBe(basicMethods[1].id);
|
|
56
|
+
|
|
57
|
+
expect(client.supportedAuthSchemes.basic).toBe(true);
|
|
58
|
+
|
|
59
|
+
const secondMethod = basicMethods[1];
|
|
60
|
+
const picked = await client.login(
|
|
61
|
+
testConfig.test_user,
|
|
62
|
+
testConfig.test_password,
|
|
63
|
+
secondMethod.id,
|
|
64
|
+
);
|
|
65
|
+
expect(picked.jwtToken).not.toBe("");
|
|
66
|
+
|
|
67
|
+
const unpicked = await client.login(testConfig.test_user, testConfig.test_password);
|
|
68
|
+
expect(unpicked.jwtToken).not.toBe("");
|
|
69
|
+
|
|
70
|
+
await expect(
|
|
71
|
+
client.login(testConfig.test_user, testConfig.test_password, "no-such-method"),
|
|
72
|
+
).rejects.toThrow();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Skipped: this environment's backend cannot be configured with two htpasswd login methods.
|
|
76
|
+
test.skip("loginMethods and login address two identically-described htpasswd methods by id (gRPC)", async () => {
|
|
77
|
+
const testConfig = getTestConfig();
|
|
78
|
+
await runMultiMethodCases(testConfig.address);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// Skipped: this environment's backend cannot be configured with two htpasswd login methods.
|
|
82
|
+
test.skip("loginMethods and login address two identically-described htpasswd methods by id (REST)", async () => {
|
|
83
|
+
const testConfig = getTestConfig();
|
|
84
|
+
const separator = testConfig.address.includes("?") ? "&" : "?";
|
|
85
|
+
await runMultiMethodCases(`${testConfig.address}${separator}wire-protocol=rest`);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
test("beginSSOLogin rejects an id no configured method carries, and reports no SSO configured when unpicked", async () => {
|
|
89
|
+
const testConfig = getTestConfig();
|
|
90
|
+
const client = await UnauthenticatedPlClient.build(plAddressToTestConfig(testConfig.address));
|
|
91
|
+
|
|
92
|
+
await expect(client.beginSSOLogin("no-such-method")).rejects.toThrow();
|
|
93
|
+
|
|
94
|
+
try {
|
|
95
|
+
await client.beginSSOLogin();
|
|
96
|
+
throw new Error("expected beginSSOLogin() to reject on a server with no SSO method configured");
|
|
97
|
+
} catch (e) {
|
|
98
|
+
expect(isUnimplementedError(e)).toBe(true);
|
|
99
|
+
}
|
|
100
|
+
});
|
|
@@ -18,6 +18,7 @@ export type SSOFlowType = "public_pkce";
|
|
|
18
18
|
* may surface (`userIdClaim`, `groupsClaim`). */
|
|
19
19
|
export type SSOAuthMethod = {
|
|
20
20
|
id: string;
|
|
21
|
+
title: string;
|
|
21
22
|
description: string;
|
|
22
23
|
issuer: string;
|
|
23
24
|
clientId: string;
|
|
@@ -48,6 +49,14 @@ export type SSOLoginAttempt = {
|
|
|
48
49
|
clientSecret?: string;
|
|
49
50
|
};
|
|
50
51
|
|
|
52
|
+
/** One login method the backend advertises, of any kind. Every advertised method keeps its own
|
|
53
|
+
* `id`, `title`, `description` and kind. Two same-kind methods, such as two LDAP directories, are
|
|
54
|
+
* two entries a caller can name apart and never collapsed into one. See {@link UnauthenticatedPlClient.loginMethods}. */
|
|
55
|
+
export type LoginMethod =
|
|
56
|
+
| { kind: "basic"; id: string; title: string; description: string }
|
|
57
|
+
| { kind: "token"; id: string; title: string; description: string }
|
|
58
|
+
| ({ kind: "sso" } & SSOAuthMethod);
|
|
59
|
+
|
|
51
60
|
/** Primarily used for initial authentication (login) */
|
|
52
61
|
export class UnauthenticatedPlClient {
|
|
53
62
|
public readonly ll: LLPlClient;
|
|
@@ -82,7 +91,9 @@ export class UnauthenticatedPlClient {
|
|
|
82
91
|
|
|
83
92
|
/** Classifies the advertised authentication methods by credential scheme.
|
|
84
93
|
* On legacy backends (no auth:v2) the typed oneof is empty; callers fall through to {@link login}
|
|
85
|
-
* which uses the legacy GetJWTToken path.
|
|
94
|
+
* which uses the legacy GetJWTToken path.
|
|
95
|
+
* @deprecated collapses every basic-kind method into one boolean; use {@link loginMethods} to
|
|
96
|
+
* see each advertised method's own id. `login()` still reads this to choose the credential path. */
|
|
86
97
|
public get supportedAuthSchemes(): { basic: boolean; token: boolean } {
|
|
87
98
|
const result = { basic: false, token: false };
|
|
88
99
|
for (const m of this.ll.authMethodsSync.methods) {
|
|
@@ -92,8 +103,37 @@ export class UnauthenticatedPlClient {
|
|
|
92
103
|
return result;
|
|
93
104
|
}
|
|
94
105
|
|
|
106
|
+
/** Builds the {@link SSOAuthMethod} projection an advertised SSO entry carries, or `undefined`
|
|
107
|
+
* for a flow no client here can drive. Shared by {@link ssoConfig} and {@link loginMethods},
|
|
108
|
+
* which each apply their own rule for an unsupported flow. */
|
|
109
|
+
private toSSOAuthMethod(
|
|
110
|
+
method: AuthAPI_ListMethods_Response["methods"][number],
|
|
111
|
+
): SSOAuthMethod | undefined {
|
|
112
|
+
if (method.method.oneofKind !== "sso") return undefined;
|
|
113
|
+
const sso = method.method.sso;
|
|
114
|
+
if (sso.flowType !== AuthAPI_ListMethods_SSOAuthMethod_FlowType.PUBLIC_PKCE) return undefined;
|
|
115
|
+
return {
|
|
116
|
+
id: method.id,
|
|
117
|
+
title: method.title || method.description || method.id,
|
|
118
|
+
description: method.description,
|
|
119
|
+
issuer: sso.issuer,
|
|
120
|
+
clientId: sso.clientId,
|
|
121
|
+
scopes: sso.scopes,
|
|
122
|
+
resource: sso.resource,
|
|
123
|
+
prompt: sso.prompt,
|
|
124
|
+
redirectPorts: sso.redirectPorts,
|
|
125
|
+
subjectTokenSource: sso.subjectTokenSource,
|
|
126
|
+
userIdClaim: sso.userIdClaim,
|
|
127
|
+
groupsClaim: sso.groupsClaim,
|
|
128
|
+
accessType: sso.accessType || undefined,
|
|
129
|
+
flowType: "public_pkce",
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
|
|
95
133
|
/** Projection of the first advertised SSO method, derived from {@link authMethodsSync}.
|
|
96
|
-
* v1: at most one SSO method per deployment, so callers do not need to discriminate.
|
|
134
|
+
* v1: at most one SSO method per deployment, so callers do not need to discriminate.
|
|
135
|
+
* @deprecated surfaces only the first advertised SSO method; use {@link loginMethods} to see
|
|
136
|
+
* every advertised method, of every kind. */
|
|
97
137
|
public ssoConfig(): SSOAuthMethod | undefined {
|
|
98
138
|
for (const method of this.ll.authMethodsSync.methods) {
|
|
99
139
|
if (method.method.oneofKind !== "sso") continue;
|
|
@@ -101,42 +141,65 @@ export class UnauthenticatedPlClient {
|
|
|
101
141
|
if (sso.flowType !== AuthAPI_ListMethods_SSOAuthMethod_FlowType.PUBLIC_PKCE) {
|
|
102
142
|
throw new Error(`ssoConfig: unsupported SSO flow type ${sso.flowType}`);
|
|
103
143
|
}
|
|
104
|
-
return
|
|
105
|
-
id: method.id,
|
|
106
|
-
description: method.description,
|
|
107
|
-
issuer: sso.issuer,
|
|
108
|
-
clientId: sso.clientId,
|
|
109
|
-
scopes: sso.scopes,
|
|
110
|
-
resource: sso.resource,
|
|
111
|
-
prompt: sso.prompt,
|
|
112
|
-
redirectPorts: sso.redirectPorts,
|
|
113
|
-
subjectTokenSource: sso.subjectTokenSource,
|
|
114
|
-
userIdClaim: sso.userIdClaim,
|
|
115
|
-
groupsClaim: sso.groupsClaim,
|
|
116
|
-
accessType: sso.accessType || undefined,
|
|
117
|
-
flowType: "public_pkce",
|
|
118
|
-
};
|
|
144
|
+
return this.toSSOAuthMethod(method);
|
|
119
145
|
}
|
|
120
146
|
return undefined;
|
|
121
147
|
}
|
|
122
148
|
|
|
123
|
-
/**
|
|
149
|
+
/** Every login method the backend advertises, of every kind, in advertised order, each
|
|
150
|
+
* keeping its own `id`, `title`, `description` and kind. An entry with no usable method arm, or an
|
|
151
|
+
* SSO entry whose flow no client here can drive, is dropped rather than failing the whole
|
|
152
|
+
* list, which is why this accessor skips where {@link ssoConfig} throws. */
|
|
153
|
+
public loginMethods(): LoginMethod[] {
|
|
154
|
+
const picked: LoginMethod[] = [];
|
|
155
|
+
for (const method of this.ll.authMethodsSync.methods) {
|
|
156
|
+
switch (method.method.oneofKind) {
|
|
157
|
+
case "basic":
|
|
158
|
+
case "token":
|
|
159
|
+
picked.push({
|
|
160
|
+
kind: method.method.oneofKind,
|
|
161
|
+
id: method.id,
|
|
162
|
+
title: method.title || method.description || method.id,
|
|
163
|
+
description: method.description,
|
|
164
|
+
});
|
|
165
|
+
break;
|
|
166
|
+
case "sso": {
|
|
167
|
+
const sso = this.toSSOAuthMethod(method);
|
|
168
|
+
if (sso !== undefined) picked.push({ kind: "sso", ...sso });
|
|
169
|
+
break;
|
|
170
|
+
}
|
|
171
|
+
default:
|
|
172
|
+
// No arm at all — a legacy backend advertising nothing pickable.
|
|
173
|
+
break;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return picked;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/** Login with username and password.
|
|
124
180
|
*
|
|
125
|
-
*
|
|
126
|
-
*
|
|
127
|
-
* - if only token auth is offered, treats `password` as an opaque bearer token and
|
|
128
|
-
* sends {@link LLPlClient.loginWithToken} (so deployments configured for static-token
|
|
129
|
-
* auth still log in without the caller switching methods).
|
|
181
|
+
* Routes to {@link LLPlClient.loginBasic} or {@link LLPlClient.loginWithToken} based on the
|
|
182
|
+
* advertised method `idP` names. On legacy backends, uses GetJWTToken with Basic header.
|
|
130
183
|
*
|
|
131
|
-
*
|
|
132
|
-
*
|
|
133
|
-
|
|
184
|
+
* `idP` names the advertised method. A named basic-kind method routes to the basic branch;
|
|
185
|
+
* a named token-kind method routes to the token branch even when the backend also advertises
|
|
186
|
+
* a basic method — the token wire carries no selector, so the id itself is dropped there and
|
|
187
|
+
* only the branch choice is kept. Omitted, or naming no advertised method, falls back to
|
|
188
|
+
* today's first-match behavior: basic wins over token when both are advertised. */
|
|
189
|
+
public async login(user: string, password: string, idP?: string): Promise<AuthInformation> {
|
|
134
190
|
try {
|
|
135
191
|
let token: string;
|
|
136
192
|
if (this.ll.hasCapability("auth:v2")) {
|
|
137
193
|
const schemes = this.supportedAuthSchemes;
|
|
138
|
-
|
|
139
|
-
|
|
194
|
+
const namedKind =
|
|
195
|
+
idP === undefined ? undefined : this.loginMethods().find((m) => m.id === idP)?.kind;
|
|
196
|
+
if (namedKind === "token") {
|
|
197
|
+
token = await this.ll.loginWithToken(password);
|
|
198
|
+
} else if (schemes.basic) {
|
|
199
|
+
token =
|
|
200
|
+
idP === undefined
|
|
201
|
+
? await this.ll.loginBasic(user, password)
|
|
202
|
+
: await this.ll.loginBasic(user, password, { idP });
|
|
140
203
|
} else if (schemes.token) {
|
|
141
204
|
token = await this.ll.loginWithToken(password);
|
|
142
205
|
} else {
|
|
@@ -157,9 +220,12 @@ export class UnauthenticatedPlClient {
|
|
|
157
220
|
}
|
|
158
221
|
|
|
159
222
|
/** Request fresh server-issued login material. v1 only emits the public-PKCE flow;
|
|
160
|
-
* desktop MUST place the returned `nonce` verbatim into the OIDC auth-request.
|
|
161
|
-
|
|
162
|
-
|
|
223
|
+
* desktop MUST place the returned `nonce` verbatim into the OIDC auth-request. `idP` names
|
|
224
|
+
* the advertised SSO method to route to; omitted, the backend keeps its current first-match
|
|
225
|
+
* behaviour. */
|
|
226
|
+
public async beginSSOLogin(idP?: string): Promise<SSOLoginAttempt> {
|
|
227
|
+
const attempt =
|
|
228
|
+
idP === undefined ? await this.ll.beginSSOLogin() : await this.ll.beginSSOLogin(idP);
|
|
163
229
|
return {
|
|
164
230
|
flow: "public_pkce",
|
|
165
231
|
nonce: attempt.nonce,
|
|
@@ -168,10 +234,18 @@ export class UnauthenticatedPlClient {
|
|
|
168
234
|
};
|
|
169
235
|
}
|
|
170
236
|
|
|
171
|
-
/** Forward the verbatim IdP `/token` response body and receive a Platforma JWT.
|
|
172
|
-
|
|
237
|
+
/** Forward the verbatim IdP `/token` response body and receive a Platforma JWT. `idP` names
|
|
238
|
+
* the advertised SSO method to route to; omitted, the backend keeps its current first-match
|
|
239
|
+
* behaviour. */
|
|
240
|
+
public async loginSSO(payload: {
|
|
241
|
+
tokenResponse: Uint8Array;
|
|
242
|
+
idP?: string;
|
|
243
|
+
}): Promise<AuthInformation> {
|
|
173
244
|
try {
|
|
174
|
-
const jwtToken =
|
|
245
|
+
const jwtToken =
|
|
246
|
+
payload.idP === undefined
|
|
247
|
+
? await this.ll.loginSSO(payload.tokenResponse)
|
|
248
|
+
: await this.ll.loginSSO(payload.tokenResponse, payload.idP);
|
|
175
249
|
if (jwtToken === "") throw new Error("empty token");
|
|
176
250
|
return { jwtToken };
|
|
177
251
|
} catch (e: any) {
|