@plainkey/browser 0.1.0 → 0.2.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/dist/index.d.mts +2 -2
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +8 -8
- package/dist/index.mjs.map +1 -1
- package/package.json +29 -29
package/dist/index.d.mts
CHANGED
|
@@ -74,11 +74,11 @@ type LoginCompleteResponse = {
|
|
|
74
74
|
//#endregion
|
|
75
75
|
//#region src/plainkey-client.d.ts
|
|
76
76
|
type PlainKeyClientParams = {
|
|
77
|
-
|
|
77
|
+
projectId: string;
|
|
78
78
|
baseUrl?: string;
|
|
79
79
|
};
|
|
80
80
|
declare class PlainKeyClient {
|
|
81
|
-
private readonly
|
|
81
|
+
private readonly projectId;
|
|
82
82
|
private readonly baseUrl;
|
|
83
83
|
constructor(clientParams: PlainKeyClientParams);
|
|
84
84
|
/**
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/types/requests.ts","../src/types/responses.ts","../src/plainkey-client.ts"],"sourcesContent":[],"mappings":";;;;KAIY,wBAAA;;EAAA,YAAA,CAAA,EAEK,MAFL,CAAA,MAAwB,EAAA,OAEnB,CAAA;AAGjB,CAAA;AAAuC,KAA3B,2BAAA,GAA2B;gBACrB,EAAA,cAAA;YACJ,EAAA,wBAAA;CAAwB;AAI1B,KAAA,0BAAA,GAA0B;EAI1B,cAAA,EAHM,cAGN;CAA6B;AACvB,KADN,6BAAA,GACM;gBACJ,EADI,cACJ;EAAwB,UAAA,EAAxB,wBAAwB;AAItC,CAAA;AAIY,KAJA,iBAAA,GAIoB;mBAHb;;KAGP,oBAAA;ECtBA,sBAAa,EDuBC,0BCvBD;AAKzB,CAAA;;;KALY,aAAA;;ADHZ,CAAA;AAKY,KCGA,yBAAA,GDH2B;EAAA,IAAA,ECI/B,UDJ+B;SACrB,ECIP,sCDJO;;AACoB,KCM1B,aAAA,GDN0B;EAI1B,SAAA,EAAA,MAAA;EAIA,KAAA,EAAA,MAAA;EAA6B,gBAAA,EAAA,MAAA;WACvB,EAAA,MAAA;cACJ,EAAA,MAAA;CAAwB;AAI1B,KCAA,4BAAA,GDCO;EAGP,OAAA,EAAA,OAAA;QCFJ;SACC;;IArBG,EAAA,EAAA,MAAA;IAKA,UAAA,EAAA,MAAA;EAAyB,CAAA;;AAE1B,KAsBC,2BAAA,GAtBD;EAAsC,IAAA,EAuBzC,UAvByC;EAGrC,OAAA,EAqBD,sCArBc;AAQzB,CAAA;AAAwC,KAgB5B,8BAAA,GAhB4B;SAEhC,EAAA,OAAA;MACC,EAeD,UAfC;EAAa,KAAA,EAgBb,aAhBa;EAQV,UAAA,EAAA;IAA2B,EAAA,EAAA,MAAA;IAC/B,UAAA,EAAA,MAAA;;CACyC;AAGrC,KAWA,kBAAA,GAXA;EAA8B,SAAA,EAAA,MAAA;QAElC,CAAA,EAAA,MAAA;SACC,EAWE,qCAXF;CAAa;AAQV,KAMA,qBAAA,GAHD;EAGC,QAAA,EAAA,OAAA;EAAqB,IAAA,EAEzB,UAFyB;OAEzB,EACC,aADD;;;;KCtCI,oBAAA;;EFlBA,OAAA,CAAA,EAAA,MAAA;AAKZ,CAAA;AAAuC,
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/types/requests.ts","../src/types/responses.ts","../src/plainkey-client.ts"],"sourcesContent":[],"mappings":";;;;KAIY,wBAAA;;EAAA,YAAA,CAAA,EAEK,MAFL,CAAA,MAAwB,EAAA,OAEnB,CAAA;AAGjB,CAAA;AAAuC,KAA3B,2BAAA,GAA2B;gBACrB,EAAA,cAAA;YACJ,EAAA,wBAAA;CAAwB;AAI1B,KAAA,0BAAA,GAA0B;EAI1B,cAAA,EAHM,cAGN;CAA6B;AACvB,KADN,6BAAA,GACM;gBACJ,EADI,cACJ;EAAwB,UAAA,EAAxB,wBAAwB;AAItC,CAAA;AAIY,KAJA,iBAAA,GAIoB;mBAHb;;KAGP,oBAAA;ECtBA,sBAAa,EDuBC,0BCvBD;AAKzB,CAAA;;;KALY,aAAA;;ADHZ,CAAA;AAKY,KCGA,yBAAA,GDH2B;EAAA,IAAA,ECI/B,UDJ+B;SACrB,ECIP,sCDJO;;AACoB,KCM1B,aAAA,GDN0B;EAI1B,SAAA,EAAA,MAAA;EAIA,KAAA,EAAA,MAAA;EAA6B,gBAAA,EAAA,MAAA;WACvB,EAAA,MAAA;cACJ,EAAA,MAAA;CAAwB;AAI1B,KCAA,4BAAA,GDCO;EAGP,OAAA,EAAA,OAAA;QCFJ;SACC;;IArBG,EAAA,EAAA,MAAA;IAKA,UAAA,EAAA,MAAA;EAAyB,CAAA;;AAE1B,KAsBC,2BAAA,GAtBD;EAAsC,IAAA,EAuBzC,UAvByC;EAGrC,OAAA,EAqBD,sCArBc;AAQzB,CAAA;AAAwC,KAgB5B,8BAAA,GAhB4B;SAEhC,EAAA,OAAA;MACC,EAeD,UAfC;EAAa,KAAA,EAgBb,aAhBa;EAQV,UAAA,EAAA;IAA2B,EAAA,EAAA,MAAA;IAC/B,UAAA,EAAA,MAAA;;CACyC;AAGrC,KAWA,kBAAA,GAXA;EAA8B,SAAA,EAAA,MAAA;QAElC,CAAA,EAAA,MAAA;SACC,EAWE,qCAXF;CAAa;AAQV,KAMA,qBAAA,GAHD;EAGC,QAAA,EAAA,OAAA;EAAqB,IAAA,EAEzB,UAFyB;OAEzB,EACC,aADD;;;;KCtCI,oBAAA;;EFlBA,OAAA,CAAA,EAAA,MAAA;AAKZ,CAAA;AAAuC,cEmB1B,cAAA,CFnB0B;mBACrB,SAAA;mBACJ,OAAA;EAAwB,WAAA,CAAA,YAAA,EEqBV,oBFrBU;EAI1B;AAIZ;;;cAEc,CAAA,WAAA,EEsBoB,wBFtBpB,CAAA,EEsB+C,OFtB/C,CEsBuD,4BFtBvD,CAAA;EAAwB;AAItC;AAIA;;6BEyEiB,6BACZ,QAAQ;;ADhGb;AAKA;EAAqC,KAAA,CAAA,WAAA,ECoJV,iBDpJU,CAAA,ECoJU,ODpJV,CCoJkB,qBDpJlB,CAAA"}
|
package/dist/index.mjs
CHANGED
|
@@ -3,8 +3,8 @@ import { startAuthentication, startRegistration } from "@simplewebauthn/browser"
|
|
|
3
3
|
//#region src/plainkey-client.ts
|
|
4
4
|
var PlainKeyClient = class {
|
|
5
5
|
constructor(clientParams) {
|
|
6
|
-
const {
|
|
7
|
-
this.
|
|
6
|
+
const { projectId, baseUrl = "https://api.plainkey.io" } = clientParams;
|
|
7
|
+
this.projectId = projectId;
|
|
8
8
|
this.baseUrl = baseUrl.replace(/\/$/, "");
|
|
9
9
|
}
|
|
10
10
|
/**
|
|
@@ -14,7 +14,7 @@ var PlainKeyClient = class {
|
|
|
14
14
|
async Registration(beginParams) {
|
|
15
15
|
const headers = new Headers({
|
|
16
16
|
"Content-Type": "application/json",
|
|
17
|
-
"
|
|
17
|
+
"x-project-id": this.projectId
|
|
18
18
|
});
|
|
19
19
|
const beginResponse = await fetch(`${this.baseUrl}/user/register/begin`, {
|
|
20
20
|
method: "POST",
|
|
@@ -36,7 +36,7 @@ var PlainKeyClient = class {
|
|
|
36
36
|
method: "POST",
|
|
37
37
|
headers: {
|
|
38
38
|
"Content-Type": "application/json",
|
|
39
|
-
"
|
|
39
|
+
"x-project-id": this.projectId
|
|
40
40
|
},
|
|
41
41
|
credentials: "include",
|
|
42
42
|
body: JSON.stringify(completeParams)
|
|
@@ -56,7 +56,7 @@ var PlainKeyClient = class {
|
|
|
56
56
|
async AddCredential(beginParams) {
|
|
57
57
|
const headers = new Headers({
|
|
58
58
|
"Content-Type": "application/json",
|
|
59
|
-
"
|
|
59
|
+
"x-project-id": this.projectId
|
|
60
60
|
});
|
|
61
61
|
const beginResponse = await fetch(`${this.baseUrl}/user/credential/begin`, {
|
|
62
62
|
method: "POST",
|
|
@@ -78,7 +78,7 @@ var PlainKeyClient = class {
|
|
|
78
78
|
method: "POST",
|
|
79
79
|
headers: {
|
|
80
80
|
"Content-Type": "application/json",
|
|
81
|
-
"
|
|
81
|
+
"x-project-id": this.projectId
|
|
82
82
|
},
|
|
83
83
|
credentials: "include",
|
|
84
84
|
body: JSON.stringify(completeParams)
|
|
@@ -99,7 +99,7 @@ var PlainKeyClient = class {
|
|
|
99
99
|
method: "POST",
|
|
100
100
|
headers: {
|
|
101
101
|
"Content-Type": "application/json",
|
|
102
|
-
"
|
|
102
|
+
"x-project-id": this.projectId
|
|
103
103
|
},
|
|
104
104
|
credentials: "include",
|
|
105
105
|
body: JSON.stringify(beginParams)
|
|
@@ -117,7 +117,7 @@ var PlainKeyClient = class {
|
|
|
117
117
|
method: "POST",
|
|
118
118
|
headers: {
|
|
119
119
|
"Content-Type": "application/json",
|
|
120
|
-
"
|
|
120
|
+
"x-project-id": this.projectId
|
|
121
121
|
},
|
|
122
122
|
credentials: "include",
|
|
123
123
|
body: JSON.stringify(completeParams)
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["errorData: ErrorResponse","credential: RegistrationResponseJSON","completeParams: RegistrationCompleteRequest","response: RegistrationCompleteResponse","completeParams: UserCredentialCompleteRequest","response: UserCredentialCompleteResponse","beginResponseData: LoginBeginResponse","authenticationResponse: AuthenticationResponseJSON","completeParams: LoginCompleteRequest","verificationResponseData: LoginCompleteResponse"],"sources":["../src/plainkey-client.ts"],"sourcesContent":["import { startAuthentication, startRegistration } from \"@simplewebauthn/browser\"\r\nimport { RegistrationResponseJSON, AuthenticationResponseJSON } from \"@simplewebauthn/browser\"\r\n\r\nimport type {\r\n RegistrationBeginRequest,\r\n RegistrationCompleteRequest,\r\n UserCredentialBeginRequest,\r\n UserCredentialCompleteRequest,\r\n LoginBeginRequest,\r\n LoginCompleteRequest\r\n} from \"./types/requests\"\r\n\r\nimport type {\r\n RegistrationBeginResponse,\r\n RegistrationCompleteResponse,\r\n UserCredentialBeginResponse,\r\n UserCredentialCompleteResponse,\r\n LoginBeginResponse,\r\n LoginCompleteResponse,\r\n ErrorResponse\r\n} from \"./types/responses\"\r\n\r\nexport type PlainKeyClientParams = {\r\n // The client ID tied to the project.\r\n clientId: string\r\n\r\n // The base URL of the PlainKey API.\r\n baseUrl?: string\r\n}\r\n\r\n// TODO: Account for errors like this: \"Unexpected token 'R', \"Response v\"... is not valid JSON\"\r\nexport class PlainKeyClient {\r\n private readonly clientId: string\r\n private readonly baseUrl: string\r\n\r\n constructor(clientParams: PlainKeyClientParams) {\r\n const { clientId, baseUrl = \"https://api.plainkey.io\" } = clientParams\r\n\r\n this.clientId = clientId\r\n this.baseUrl = baseUrl.replace(/\\/$/, \"\") // Remove trailing slash\r\n }\r\n\r\n /**\r\n * Registration of a new user with passkey.\r\n * Creates a new user and adds a credential to it.\r\n */\r\n async Registration(beginParams: RegistrationBeginRequest): Promise<RegistrationCompleteResponse> {\r\n // Step 1: Get registration options from server\r\n const headers = new Headers({\r\n \"Content-Type\": \"application/json\",\r\n \"client-id\": this.clientId\r\n })\r\n\r\n const beginResponse = await fetch(`${this.baseUrl}/user/register/begin`, {\r\n method: \"POST\",\r\n headers,\r\n credentials: \"include\",\r\n body: JSON.stringify(beginParams)\r\n })\r\n\r\n if (!beginResponse.ok) {\r\n const errorData: ErrorResponse = await beginResponse.json()\r\n throw new Error(errorData.error)\r\n }\r\n\r\n const { options, user } = (await beginResponse.json()) as RegistrationBeginResponse\r\n\r\n // Step 2: Create credential using browser's WebAuthn API\r\n const credential: RegistrationResponseJSON = await startRegistration({\r\n optionsJSON: options\r\n })\r\n\r\n // Step 3: Send credential to server for verification\r\n const completeParams: RegistrationCompleteRequest = {\r\n userIdentifier: { userId: user.id },\r\n credential\r\n }\r\n\r\n const completeResponse = await fetch(`${this.baseUrl}/user/register/complete`, {\r\n method: \"POST\",\r\n headers: {\r\n \"Content-Type\": \"application/json\",\r\n \"client-id\": this.clientId\r\n },\r\n credentials: \"include\",\r\n body: JSON.stringify(completeParams)\r\n })\r\n\r\n if (!completeResponse.ok) {\r\n const errorData: ErrorResponse = await completeResponse.json()\r\n throw new Error(errorData.error)\r\n }\r\n\r\n // Intentionally not throwing errors on verification failure - UI should handle this.\r\n const response: RegistrationCompleteResponse = await completeResponse.json()\r\n if (!response) throw new Error(\"No registration response from server\")\r\n\r\n return response\r\n }\r\n\r\n /**\r\n * Add credential to existing user.\r\n * Requires valid user authentication token (log user in first which will set a user token cookie, then call this).\r\n */\r\n async AddCredential(\r\n beginParams: UserCredentialBeginRequest\r\n ): Promise<UserCredentialCompleteResponse> {\r\n // Step 1: Get credential registration options from server\r\n const headers = new Headers({\r\n \"Content-Type\": \"application/json\",\r\n \"client-id\": this.clientId\r\n })\r\n\r\n const beginResponse = await fetch(`${this.baseUrl}/user/credential/begin`, {\r\n method: \"POST\",\r\n headers,\r\n credentials: \"include\",\r\n body: JSON.stringify(beginParams)\r\n })\r\n\r\n if (!beginResponse.ok) {\r\n const errorData: ErrorResponse = await beginResponse.json()\r\n throw new Error(errorData.error)\r\n }\r\n\r\n const { options, user } = (await beginResponse.json()) as UserCredentialBeginResponse\r\n\r\n // Step 2: Create credential using browser's WebAuthn API\r\n const credential: RegistrationResponseJSON = await startRegistration({\r\n optionsJSON: options\r\n })\r\n\r\n // Step 3: Send credential to server for verification\r\n const completeParams: UserCredentialCompleteRequest = {\r\n userIdentifier: { userId: user.id },\r\n credential\r\n }\r\n\r\n const completeResponse = await fetch(`${this.baseUrl}/user/credential/complete`, {\r\n method: \"POST\",\r\n headers: {\r\n \"Content-Type\": \"application/json\",\r\n \"client-id\": this.clientId\r\n },\r\n credentials: \"include\",\r\n body: JSON.stringify(completeParams)\r\n })\r\n\r\n if (!completeResponse.ok) {\r\n const errorData: ErrorResponse = await completeResponse.json()\r\n throw new Error(errorData.error)\r\n }\r\n\r\n // Intentionally not throwing errors on verification failure - UI should handle this.\r\n const response: UserCredentialCompleteResponse = await completeResponse.json()\r\n if (!response) throw new Error(\"No credential registration response from server\")\r\n\r\n return response\r\n }\r\n\r\n /**\r\n * Performs a login ceremony.\r\n */\r\n async Login(beginParams: LoginBeginRequest): Promise<LoginCompleteResponse> {\r\n // Step 1: Get authentication options from server\r\n const beginResponse = await fetch(`${this.baseUrl}/login/begin`, {\r\n method: \"POST\",\r\n headers: {\r\n \"Content-Type\": \"application/json\",\r\n \"client-id\": this.clientId\r\n },\r\n credentials: \"include\",\r\n body: JSON.stringify(beginParams)\r\n })\r\n\r\n if (!beginResponse.ok) {\r\n const errorData: ErrorResponse = await beginResponse.json()\r\n throw new Error(errorData.error)\r\n }\r\n\r\n const beginResponseData: LoginBeginResponse = await beginResponse.json()\r\n if (!beginResponseData.options) {\r\n throw new Error(\"No options found in login begin response\")\r\n }\r\n\r\n // Step 2: Pass options to the authenticator and wait for response\r\n const authenticationResponse: AuthenticationResponseJSON = await startAuthentication({\r\n optionsJSON: beginResponseData.options\r\n })\r\n\r\n if (!authenticationResponse) {\r\n throw new Error(\"No authentication response from browser\")\r\n }\r\n\r\n // Step 3: POST the response to the server\r\n const completeParams: LoginCompleteRequest = { authenticationResponse }\r\n\r\n const verificationResponse = await fetch(`${this.baseUrl}/login/complete`, {\r\n method: \"POST\",\r\n headers: {\r\n \"Content-Type\": \"application/json\",\r\n \"client-id\": this.clientId\r\n },\r\n credentials: \"include\",\r\n body: JSON.stringify(completeParams)\r\n })\r\n\r\n if (!verificationResponse.ok) {\r\n const errorData: ErrorResponse = await verificationResponse.json()\r\n throw new Error(errorData.error)\r\n }\r\n\r\n // Intentionally not throwing errors on verification failure - UI should handle this.\r\n const verificationResponseData: LoginCompleteResponse = await verificationResponse.json()\r\n if (!verificationResponseData) throw new Error(\"No login verification response from server\")\r\n\r\n return verificationResponseData\r\n }\r\n}\r\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["errorData: ErrorResponse","credential: RegistrationResponseJSON","completeParams: RegistrationCompleteRequest","response: RegistrationCompleteResponse","completeParams: UserCredentialCompleteRequest","response: UserCredentialCompleteResponse","beginResponseData: LoginBeginResponse","authenticationResponse: AuthenticationResponseJSON","completeParams: LoginCompleteRequest","verificationResponseData: LoginCompleteResponse"],"sources":["../src/plainkey-client.ts"],"sourcesContent":["import { startAuthentication, startRegistration } from \"@simplewebauthn/browser\"\nimport { RegistrationResponseJSON, AuthenticationResponseJSON } from \"@simplewebauthn/browser\"\n\nimport type {\n RegistrationBeginRequest,\n RegistrationCompleteRequest,\n UserCredentialBeginRequest,\n UserCredentialCompleteRequest,\n LoginBeginRequest,\n LoginCompleteRequest\n} from \"./types/requests\"\n\nimport type {\n RegistrationBeginResponse,\n RegistrationCompleteResponse,\n UserCredentialBeginResponse,\n UserCredentialCompleteResponse,\n LoginBeginResponse,\n LoginCompleteResponse,\n ErrorResponse\n} from \"./types/responses\"\n\nexport type PlainKeyClientParams = {\n projectId: string\n baseUrl?: string\n}\n\n// TODO: Account for errors like this: \"Unexpected token 'R', \"Response v\"... is not valid JSON\"\nexport class PlainKeyClient {\n private readonly projectId: string\n private readonly baseUrl: string\n\n constructor(clientParams: PlainKeyClientParams) {\n const { projectId, baseUrl = \"https://api.plainkey.io\" } = clientParams\n\n this.projectId = projectId\n this.baseUrl = baseUrl.replace(/\\/$/, \"\") // Remove trailing slash\n }\n\n /**\n * Registration of a new user with passkey.\n * Creates a new user and adds a credential to it.\n */\n async Registration(beginParams: RegistrationBeginRequest): Promise<RegistrationCompleteResponse> {\n // Step 1: Get registration options from server\n const headers = new Headers({\n \"Content-Type\": \"application/json\",\n \"x-project-id\": this.projectId\n })\n\n const beginResponse = await fetch(`${this.baseUrl}/user/register/begin`, {\n method: \"POST\",\n headers,\n credentials: \"include\",\n body: JSON.stringify(beginParams)\n })\n\n if (!beginResponse.ok) {\n const errorData: ErrorResponse = await beginResponse.json()\n throw new Error(errorData.error)\n }\n\n const { options, user } = (await beginResponse.json()) as RegistrationBeginResponse\n\n // Step 2: Create credential using browser's WebAuthn API\n const credential: RegistrationResponseJSON = await startRegistration({\n optionsJSON: options\n })\n\n // Step 3: Send credential to server for verification\n const completeParams: RegistrationCompleteRequest = {\n userIdentifier: { userId: user.id },\n credential\n }\n\n const completeResponse = await fetch(`${this.baseUrl}/user/register/complete`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-project-id\": this.projectId\n },\n credentials: \"include\",\n body: JSON.stringify(completeParams)\n })\n\n if (!completeResponse.ok) {\n const errorData: ErrorResponse = await completeResponse.json()\n throw new Error(errorData.error)\n }\n\n // Intentionally not throwing errors on verification failure - UI should handle this.\n const response: RegistrationCompleteResponse = await completeResponse.json()\n if (!response) throw new Error(\"No registration response from server\")\n\n return response\n }\n\n /**\n * Add credential to existing user.\n * Requires valid user authentication token (log user in first which will set a user token cookie, then call this).\n */\n async AddCredential(\n beginParams: UserCredentialBeginRequest\n ): Promise<UserCredentialCompleteResponse> {\n // Step 1: Get credential registration options from server\n const headers = new Headers({\n \"Content-Type\": \"application/json\",\n \"x-project-id\": this.projectId\n })\n\n const beginResponse = await fetch(`${this.baseUrl}/user/credential/begin`, {\n method: \"POST\",\n headers,\n credentials: \"include\",\n body: JSON.stringify(beginParams)\n })\n\n if (!beginResponse.ok) {\n const errorData: ErrorResponse = await beginResponse.json()\n throw new Error(errorData.error)\n }\n\n const { options, user } = (await beginResponse.json()) as UserCredentialBeginResponse\n\n // Step 2: Create credential using browser's WebAuthn API\n const credential: RegistrationResponseJSON = await startRegistration({\n optionsJSON: options\n })\n\n // Step 3: Send credential to server for verification\n const completeParams: UserCredentialCompleteRequest = {\n userIdentifier: { userId: user.id },\n credential\n }\n\n const completeResponse = await fetch(`${this.baseUrl}/user/credential/complete`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-project-id\": this.projectId\n },\n credentials: \"include\",\n body: JSON.stringify(completeParams)\n })\n\n if (!completeResponse.ok) {\n const errorData: ErrorResponse = await completeResponse.json()\n throw new Error(errorData.error)\n }\n\n // Intentionally not throwing errors on verification failure - UI should handle this.\n const response: UserCredentialCompleteResponse = await completeResponse.json()\n if (!response) throw new Error(\"No credential registration response from server\")\n\n return response\n }\n\n /**\n * Performs a login ceremony.\n */\n async Login(beginParams: LoginBeginRequest): Promise<LoginCompleteResponse> {\n // Step 1: Get authentication options from server\n const beginResponse = await fetch(`${this.baseUrl}/login/begin`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-project-id\": this.projectId\n },\n credentials: \"include\",\n body: JSON.stringify(beginParams)\n })\n\n if (!beginResponse.ok) {\n const errorData: ErrorResponse = await beginResponse.json()\n throw new Error(errorData.error)\n }\n\n const beginResponseData: LoginBeginResponse = await beginResponse.json()\n if (!beginResponseData.options) {\n throw new Error(\"No options found in login begin response\")\n }\n\n // Step 2: Pass options to the authenticator and wait for response\n const authenticationResponse: AuthenticationResponseJSON = await startAuthentication({\n optionsJSON: beginResponseData.options\n })\n\n if (!authenticationResponse) {\n throw new Error(\"No authentication response from browser\")\n }\n\n // Step 3: POST the response to the server\n const completeParams: LoginCompleteRequest = { authenticationResponse }\n\n const verificationResponse = await fetch(`${this.baseUrl}/login/complete`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"x-project-id\": this.projectId\n },\n credentials: \"include\",\n body: JSON.stringify(completeParams)\n })\n\n if (!verificationResponse.ok) {\n const errorData: ErrorResponse = await verificationResponse.json()\n throw new Error(errorData.error)\n }\n\n // Intentionally not throwing errors on verification failure - UI should handle this.\n const verificationResponseData: LoginCompleteResponse = await verificationResponse.json()\n if (!verificationResponseData) throw new Error(\"No login verification response from server\")\n\n return verificationResponseData\n }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,32 +1,32 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
}
|
|
12
|
-
},
|
|
13
|
-
"sideEffects": false,
|
|
14
|
-
"files": [
|
|
15
|
-
"dist"
|
|
16
|
-
],
|
|
17
|
-
"scripts": {
|
|
18
|
-
"build": "tsdown src/index.ts --format esm --dts --sourcemap --clean",
|
|
19
|
-
"test": "vitest",
|
|
20
|
-
"prepublishOnly": "npm run build"
|
|
21
|
-
},
|
|
22
|
-
"publishConfig": {
|
|
23
|
-
"access": "public"
|
|
24
|
-
},
|
|
25
|
-
"dependencies": {
|
|
26
|
-
"@plainkey/types": "*",
|
|
27
|
-
"@simplewebauthn/browser": "^13.2.0"
|
|
28
|
-
},
|
|
29
|
-
"devDependencies": {
|
|
30
|
-
"tsdown": "^0.15.5"
|
|
2
|
+
"name": "@plainkey/browser",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "PlainKey TypeScript browser SDK",
|
|
5
|
+
"module": "dist/index.mjs",
|
|
6
|
+
"types": "dist/index.d.mts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.mts",
|
|
10
|
+
"import": "./dist/index.mjs"
|
|
31
11
|
}
|
|
12
|
+
},
|
|
13
|
+
"sideEffects": false,
|
|
14
|
+
"files": [
|
|
15
|
+
"dist"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsdown src/index.ts --format esm --dts --sourcemap --clean",
|
|
19
|
+
"test": "vitest",
|
|
20
|
+
"prepublishOnly": "npm run build"
|
|
21
|
+
},
|
|
22
|
+
"publishConfig": {
|
|
23
|
+
"access": "public"
|
|
24
|
+
},
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"@plainkey/types": "*",
|
|
27
|
+
"@simplewebauthn/browser": "^13.2.0"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"tsdown": "^0.15.5"
|
|
31
|
+
}
|
|
32
32
|
}
|