You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This guide provides a walkthrough for implementing email authentication in a Swift application using the [TurnkeyClient](../Sources/TurnkeySDK/TurnkeyClient.generated.swift). This process involves generating key pairs, handling encrypted bundles, and verifying user identity.
3
+
This guide provides a walkthrough for implementing email authentication in a Swift application using the [TurnkeyClient](../Sources/TurnkeySDK/TurnkeyClient.generated.swift). This process involves handling encrypted bundles and verifying user identity.
4
4
5
5
For a more detailed explanation of the email authentication process, please refer to the [Turnkey API documentation](https://docs.turnkey.com/features/email-auth).
6
6
@@ -24,104 +24,140 @@ let client = TurnkeyClient(proxyURL: proxyURL)
24
24
25
25
You may also forgo the use of the provided proxy middleware and make the request yourself.
26
26
27
-
## Step 2: Generate Ephemeral Key Pair
28
-
29
-
Next we'll generate an ephemeral key pair, which is will be used to decrypt the encrypted bundle sent
30
-
that the user will receive in their email.
31
-
32
-
```swift
33
-
// Create a new ephemeral private key using P-256 curve for key agreement.
34
-
let ephemeralPrivateKey = P256.KeyAgreement.PrivateKey()
35
-
36
-
// Extract the public key from the private key and convert it to a string using the x963 representation.
37
-
let targetPublicKey =try ephemeralPrivateKey.publicKey.toString(representation: .x963)
let targetPublicKey = publicKey.toString(representation: .raw)
46
32
let expirationSeconds ="3600"
47
33
let emailCustomization = Components.Schemas.EmailCustomizationParams() // Customize as needed
48
34
```
49
35
50
-
## Step 4: Send Email Authentication Request
36
+
## Step 3: Send Email Authentication Request
37
+
38
+
With the TurnkeyClient initialized, you can now send an email authentication request. This involves using the `emailAuth` method of the TurnkeyClient, passing in the necessary parameters.
39
+
40
+
### Detailed Explanation
51
41
52
-
With the TurnkeyClient initialized and the ephemeral key pair generated, you can now send an email authentication request. This involves using the `emailAuth` method of the TurnkeyClient, passing in the necessary parameters.
42
+
-**Ephemeral Key Generation**: The `emailAuth` method generates an ephemeral private key, which is used to create a public key for the authentication process. This ephemeral key is stored in memory and is used to decrypt the encrypted bundle sent to the user's email.
43
+
44
+
-**Tuple Response**: The `emailAuth` method returns a tuple containing two elements:
45
+
1.`Operations.EmailAuth.Output`: This is the output of the email authentication operation, which includes the response from the Turnkey API.
46
+
2.`verify`: A closure function that takes an encrypted bundle as input and returns an `AuthResult`. This closure uses the ephemeral private key to decrypt the bundle and verify the authentication.
53
47
54
48
```swift
55
-
letemailAuthResult=tryawait client.emailAuth(
49
+
let(output, verify)=tryawait client.emailAuth(
56
50
organizationId: organizationId,
57
51
email: email,
58
-
targetPublicKey: targetPublicKey,
59
52
apiKeyName: "your_api_key_name",
60
53
expirationSeconds: expirationSeconds,
61
54
emailCustomization: emailCustomization
62
55
)
56
+
57
+
// Assert the response
58
+
switch output {
59
+
caselet .ok(response):
60
+
switch response.body {
61
+
caselet .json(emailAuthResponse):
62
+
print(emailAuthResponse.activity.organizationId)
63
+
// We successfully initiated the email authentication request
64
+
// We'll use the verify function to verify the encrypted bundle in the next step
After sending the email authentication request, it's important to handle the response appropriately. If the authentication is successful, you should save the user's sub-organizationId from the response for future use. You'll need this organizationId later to verify the user's keys.
76
+
## Step 4: Verify Encrypted Bundle
77
+
78
+
After your user receives the encrypted bundle from Turnkey, via email, you need to verify this bundle to retrieve the necessary keys for further authentication steps. We'll use the `verify` function returned from the previous step.
79
+
80
+
### Detailed Explanation
81
+
82
+
-**AuthResult**: The `verify` function returns an `AuthResult` object, which contains:
83
+
84
+
-`whoamiResponse`: The result of calling `getWhoami`, which verifies the authentication and retrieves user details.
85
+
-`apiPublicKey` and `apiPrivateKey`: The keys obtained from the decrypted bundle, used for further authenticated requests.
86
+
87
+
-**getWhoami Call**: The `verify` function internally calls the `getWhoami` method to ensure the credentials are valid and to fetch user details from the Turnkey API.
66
88
67
89
```swift
68
-
switch emailAuthResult {
69
-
case .ok(let response):
70
-
// The user's sub-organizationId:
71
-
let organizationId = response.activity.organizationId
72
-
// Proceed with user session creation
73
-
case .undocumented(let statusCode, let undocumentedPayload):
74
-
// Handle error, possibly retry or log
90
+
do {
91
+
let authResult =tryawaitverify(bundle)
92
+
print("Verification successful: \(authResult)")
93
+
} catch {
94
+
print("Error occurred during verification: \(error)")
75
95
}
76
96
```
77
97
78
-
## Step 6: Verify Encrypted Bundle
98
+
This method will verify the encrypted bundle and provide you with the necessary authentication result.
79
99
80
-
After your user receives the encrypted bundle from Turnkey, via email, you need to decrypt this bundle to retrieve the necessary keys for further authentication steps. Use the [`decryptBundle`](../Sources/Shared/AuthManager.swift) method from the `AuthManager` to handle this.
100
+
## Step 5: Initialize the TurnkeyClient with API Keys
81
101
82
-
```swift
83
-
let (privateKey, publicKey) =try AuthManager.decryptBundle(encryptedBundle)
84
-
```
102
+
After successfully verifying the encrypted bundle and retrieving the private and public API keys, you can initialize a TurnkeyClient instance using these keys for further authenticated requests:
85
103
86
-
This method will decrypt the encrypted bundle and provide you with the private and public keys needed for the session.
87
-
At this point in the authentication process, you have two options:
104
+
```swift
105
+
// Use the apiPublicKey and apiPrivateKey from the authResult
106
+
let apiPublicKey = authResult.apiPublicKey
107
+
let apiPrivateKey = authResult.apiPrivateKey
88
108
89
-
1. Prompt the user for passkey authentication (using the `PasskeyManager`) and add a passkey as an authenticator.
90
-
2. Save the API private key in the keychain and use that for subsequent authentication requests.
109
+
// Initialize a new TurnkeyClient instance with the provided privateKey and publicKey
110
+
let turnkeyClient =TurnkeyClient(apiPrivateKey: apiPrivateKey, apiPublicKey: apiPublicKey)
111
+
```
91
112
92
-
Note: Since the decrypted API key is similar to a session key, it should be handled with the same level of security as authentication tokens.
113
+
## Step 6: Create Read Only Session
93
114
94
-
##Step 7: Initialize the TurnkeyClient and Verify the user
115
+
### Extract API Keys and Sub-Organization ID
95
116
96
-
After successfully decrypting the encrypted bundle and retrieving the private and public API keys, you can initialize a TurnkeyClient instance using these keys for further authenticated requests:
117
+
First, get the `apiPublicKey`and `apiPrivateKey` from the `authResult`, and retrieve the `organizationId` from the `whoamiResponse`. Then, instantiate the `TurnkeyClient`.
97
118
98
119
```swift
99
-
// ...
100
-
101
-
let apiPublicKey =try publicKey.toString(representation: .compressed)
102
-
let apiPrivateKey =try privateKey.toString(representation: .raw)
120
+
// Use the apiPublicKey and apiPrivateKey from the authResult
// Initialize a new TurnkeyClient instance with the provided privateKey and publicKey
105
144
let turnkeyClient =TurnkeyClient(apiPrivateKey: apiPrivateKey, apiPublicKey: apiPublicKey)
106
145
```
107
146
108
-
### Verifying User Credentials with getWhoami
147
+
### Create Read Only Session
109
148
110
-
After initializing the TurnkeyClient with the decrypted API keys, it is recommended to verify the validity of these credentials. This can be done using the `getWhoami` method, which checks the active status of the credentials against the Turnkey API.
111
-
112
-
Note: We're using the `organizationId` from the email authentication result as the `organizationId` for the `getWhoami` request.
149
+
Next, use the `subOrganizationId` to call the `createReadOnlySession` method on the `TurnkeyClient`.
113
150
114
151
```swift
115
152
do {
116
-
let whoamiResponse =tryawait turnkeyClient.getWhoami(organizationId: organizationId)
Copy file name to clipboardExpand all lines: docs/proxy-middleware.md
+49-4Lines changed: 49 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,4 +1,4 @@
1
-
# Prox yMiddleware
1
+
# Proxy Middleware
2
2
3
3
The [`ProxyMiddleware`](/Sources/Middleware/ProxyMiddleware.swift) is integrated into the TurnkeyClient through its initializer that accepts a proxy server URL. This setup is particularly useful for handling scenarios where direct authenticated requests are not feasible, such as during onboarding flows or when additional server-side processing is required before reaching Turnkey's backend.
4
4
@@ -8,7 +8,7 @@ Here's how you can initialize the TurnkeyClient with a proxy server URL:
8
8
importTurnkeySDK
9
9
10
10
// Initialize the TurnkeyClient with a proxy server URL
11
-
let turnkeyClient =TurnkeyClient(proxyURL: "https://your-proxy-server.com")
11
+
let turnkeyClient =TurnkeyClient(proxyURL: "https://your-proxy-server.com/api/turnkey-proxy")
12
12
```
13
13
14
14
This initializer configures the TurnkeyClient to route all requests through the specified proxy server. The proxy server is then responsible for forwarding these requests to a backend capable of authenticating them using an API private key. After authentication, the proxy server forwards the requests to Turnkey's backend and relays the response back to the client.
@@ -21,8 +21,53 @@ This setup is especially useful for operations like:
21
21
22
22
## Important Notes
23
23
24
-
-**Response Matching**: It is crucial that the response from the developer's backend matches exactly with what would be expected from Turnkey's backend. Any discrepancy in the response format or data can cause the request to fail.
25
-
-**Security**: Ensure that the proxy server is secure and only accessible to authorized entities to prevent unauthorized access and data breaches.
24
+
#### X-Forwarded-For Header
25
+
26
+
The middleware adds an `X-Forwarded-For` header to each request, which contains the original request URL. This is used to forward the request to Turnkey's backend.
It is crucial that the response from the developer's backend matches exactly with what would be expected from Turnkey's backend. Any discrepancy in the response format or data can cause the request to fail.
0 commit comments