Skip to content

Commit 2a58005

Browse files
authored
chore(auth): add swift passwordless sign in/web authn changes (#8131)
* chore(auth): add swift passwordless sign in/web authn changes * removed unused section * remove flutter blocks * fix spelling
1 parent 9e63ab6 commit 2a58005

File tree

3 files changed

+315
-16
lines changed
  • src/pages/[platform]/build-a-backend/auth

3 files changed

+315
-16
lines changed

src/pages/[platform]/build-a-backend/auth/connect-your-frontend/sign-in/index.mdx

Lines changed: 139 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1123,7 +1123,79 @@ Your application's users can also sign in using passwordless methods. To learn m
11231123
</InlineFilter>
11241124
<InlineFilter filters={["swift"]}>
11251125

1126-
{/* */}
1126+
<BlockSwitcher>
1127+
<Block name="Async/Await">
1128+
1129+
```swift
1130+
// sign in with `smsOTP` as preferred factor
1131+
func signIn(username: String) async {
1132+
do {
1133+
let pluginOptions = AWSAuthSignInOptions(
1134+
authFlowType: .userAuth(preferredFirstFactor: .smsOTP))
1135+
let signInResult = try await Amplify.Auth.signIn(
1136+
username: username,
1137+
options: .init(pluginOptions: pluginOptions))
1138+
print("Sign in succeeded. Next step: \(signInResult.nextStep)")
1139+
} catch let error as AuthError {
1140+
print("Sign in failed \(error)")
1141+
} catch {
1142+
print("Unexpected error: \(error)")
1143+
}
1144+
}
1145+
1146+
// confirm sign in with the code received
1147+
func confirmSignIn() async {
1148+
do {
1149+
let signInResult = try await Amplify.Auth.confirmSignIn(challengeResponse: "<confirmation code received via SMS>")
1150+
print("Confirm sign in succeeded. Next step: \(signInResult.nextStep)")
1151+
} catch let error as AuthError {
1152+
print("Confirm sign in failed \(error)")
1153+
} catch {
1154+
print("Unexpected error: \(error)")
1155+
}
1156+
}
1157+
1158+
```
1159+
1160+
</Block>
1161+
<Block name="Combine">
1162+
1163+
```swift
1164+
// sign in with `smsOTP` as preferred factor
1165+
func signIn(username: String) -> AnyCancellable {
1166+
Amplify.Publisher.create {
1167+
let pluginOptions = AWSAuthSignInOptions(
1168+
authFlowType: .userAuth(preferredFirstFactor: .smsOTP))
1169+
try await Amplify.Auth.signIn(
1170+
username: username,
1171+
options: .init(pluginOptions: pluginOptions))
1172+
}.sink {
1173+
if case let .failure(authError) = $0 {
1174+
print("Sign in failed \(authError)")
1175+
}
1176+
}
1177+
receiveValue: { signInResult in
1178+
print("Sign in succeeded. Next step: \(signInResult.nextStep)")
1179+
}
1180+
}
1181+
1182+
// confirm sign in with the code received
1183+
func confirmSignIn() -> AnyCancellable {
1184+
Amplify.Publisher.create {
1185+
try await Amplify.Auth.confirmSignIn(challengeResponse: "<confirmation code received via SMS>")
1186+
}.sink {
1187+
if case let .failure(authError) = $0 {
1188+
print("Confirm sign in failed \(authError)")
1189+
}
1190+
}
1191+
receiveValue: { signInResult in
1192+
print("Confirm sign in succeeded. Next step: \(signInResult.nextStep)")
1193+
}
1194+
}
1195+
```
1196+
1197+
</Block>
1198+
</BlockSwitcher>
11271199

11281200
</InlineFilter>
11291201

@@ -1143,26 +1215,78 @@ Your application's users can also sign in using passwordless methods. To learn m
11431215
</InlineFilter>
11441216
<InlineFilter filters={["swift"]}>
11451217

1146-
{/* */}
1147-
1148-
</InlineFilter>
1149-
1150-
### WebAuthn Passkeys
1218+
<BlockSwitcher>
1219+
<Block name="Async/Await">
11511220

1152-
{/* blurb with supplemental information about handling sign-in, events, etc. */}
1221+
```swift
1222+
// sign in with `emailOTP` as preferred factor
1223+
func signIn(username: String) async {
1224+
do {
1225+
let pluginOptions = AWSAuthSignInOptions(
1226+
authFlowType: .userAuth(preferredFirstFactor: .emailOTP))
1227+
let signInResult = try await Amplify.Auth.signIn(
1228+
username: username,
1229+
options: .init(pluginOptions: pluginOptions))
1230+
print("Sign in succeeded. Next step: \(signInResult.nextStep)")
1231+
} catch let error as AuthError {
1232+
print("Sign in failed \(error)")
1233+
} catch {
1234+
print("Unexpected error: \(error)")
1235+
}
1236+
}
11531237

1154-
<InlineFilter filters={["angular", "javascript", "nextjs", "react", "react-native", "vue"]}>
1238+
// confirm sign in with the code received
1239+
func confirmSignIn() async {
1240+
do {
1241+
let signInResult = try await Amplify.Auth.confirmSignIn(challengeResponse: "<confirmation code received via SMS>")
1242+
print("Confirm sign in succeeded. Next step: \(signInResult.nextStep)")
1243+
} catch let error as AuthError {
1244+
print("Confirm sign in failed \(error)")
1245+
} catch {
1246+
print("Unexpected error: \(error)")
1247+
}
1248+
}
11551249

1156-
{/* */}
1250+
```
11571251

1158-
</InlineFilter>
1159-
<InlineFilter filters={["android"]}>
1252+
</Block>
1253+
<Block name="Combine">
11601254

1161-
{/* */}
1255+
```swift
1256+
// sign in with `emailOTP` as preferred factor
1257+
func signIn(username: String) -> AnyCancellable {
1258+
Amplify.Publisher.create {
1259+
let pluginOptions = AWSAuthSignInOptions(
1260+
authFlowType: .userAuth(preferredFirstFactor: .emailOTP))
1261+
try await Amplify.Auth.signIn(
1262+
username: username,
1263+
options: .init(pluginOptions: pluginOptions))
1264+
}.sink {
1265+
if case let .failure(authError) = $0 {
1266+
print("Sign in failed \(authError)")
1267+
}
1268+
}
1269+
receiveValue: { signInResult in
1270+
print("Sign in succeeded. Next step: \(signInResult.nextStep)")
1271+
}
1272+
}
11621273

1163-
</InlineFilter>
1164-
<InlineFilter filters={["swift"]}>
1274+
// confirm sign in with the code received
1275+
func confirmSignIn() -> AnyCancellable {
1276+
Amplify.Publisher.create {
1277+
try await Amplify.Auth.confirmSignIn(challengeResponse: "<confirmation code received via SMS>")
1278+
}.sink {
1279+
if case let .failure(authError) = $0 {
1280+
print("Confirm sign in failed \(authError)")
1281+
}
1282+
}
1283+
receiveValue: { signInResult in
1284+
print("Confirm sign in succeeded. Next step: \(signInResult.nextStep)")
1285+
}
1286+
}
1287+
```
11651288

1166-
{/* */}
1289+
</Block>
1290+
</BlockSwitcher>
11671291

11681292
</InlineFilter>

src/pages/[platform]/build-a-backend/auth/connect-your-frontend/switching-authentication-flows/index.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ guard case .continueSignInWithFirstFactorSelection(let availableFactors) = signI
6969
print("Available factors: \(availableFactors)")
7070
```
7171

72-
The selection of the authentication method is done by the user. The user can choose from the available factors and proceed with the selected factor. You should call the `confirmSignIn` API with the selected factor to continue the sign-in process. Followign is an example if you want to proceed with the `emailOTP` factor selection:
72+
The selection of the authentication method is done by the user. The user can choose from the available factors and proceed with the selected factor. You should call the `confirmSignIn` API with the selected factor to continue the sign-in process. Following is an example if you want to proceed with the `emailOTP` factor selection:
7373

7474
```swift
7575
// Select emailOTP as the factor

src/pages/[platform]/build-a-backend/auth/manage-users/manage-webauthn-credentials/index.mdx

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,178 @@ export function getStaticProps() {
2727
};
2828
}
2929

30+
## Associate WebAuthN credentials
31+
32+
<InlineFilter filters={["angular", "javascript", "nextjs", "react", "react-native", "vue"]}>
33+
34+
{/* */}
35+
36+
</InlineFilter>
37+
<InlineFilter filters={["android"]}>
38+
39+
{/* */}
40+
41+
</InlineFilter>
42+
<InlineFilter filters={["swift"]}>
43+
44+
<BlockSwitcher>
45+
<Block name="Async/Await">
46+
47+
```swift
48+
func associateWebAuthNCredentials() async {
49+
do {
50+
try await Amplify.Auth.associateWebAuthnCredential()
51+
print("WebAuthn credential was associated")
52+
} catch {
53+
print("Associate WebAuthn Credential failed: \(error)")
54+
}
55+
}
56+
```
57+
58+
</Block>
59+
<Block name="Combine">
60+
61+
```swift
62+
func associateWebAuthNCredentials() -> AnyCancellable {
63+
Amplify.Publisher.create {
64+
try await Amplify.Auth.associateWebAuthnCredential()
65+
}.sink {
66+
print("Associate WebAuthn Credential failed: \($0)")
67+
}
68+
receiveValue: { _ in
69+
print("WebAuthn credential was associated")
70+
}
71+
}
72+
```
73+
74+
</Block>
75+
</BlockSwitcher>
76+
77+
</InlineFilter>
78+
79+
## List WebAuthN credentials
80+
81+
<InlineFilter filters={["angular", "javascript", "nextjs", "react", "react-native", "vue"]}>
82+
83+
{/* */}
84+
85+
</InlineFilter>
86+
<InlineFilter filters={["android"]}>
87+
88+
{/* */}
89+
90+
</InlineFilter>
91+
<InlineFilter filters={["swift"]}>
92+
93+
<BlockSwitcher>
94+
<Block name="Async/Await">
95+
96+
```swift
97+
func listWebAuthNCredentials() async {
98+
do {
99+
let result = try await Amplify.Auth.listWebAuthnCredentials(
100+
options: .init(pageSize: 5))
101+
102+
for credential in result.credentials {
103+
print("Credential ID: \(credential.credentialId)")
104+
print("Created At: \(credential.createdAt)")
105+
print("Relying Party Id: \(credential.relyingPartyId)")
106+
if let friendlyName = credential.friendlyName {
107+
print("Friendly name: \(friendlyName)")
108+
}
109+
}
110+
111+
// Fetch the next page
112+
if let nextToken = result.nextToken {
113+
let nextResult = try await Amplify.Auth.listWebAuthnCredentials(
114+
options: .init(
115+
pageSize: 5,
116+
nextToken: nextToken))
117+
}
118+
} catch {
119+
print("Associate WebAuthn Credential failed: \(error)")
120+
}
121+
}
122+
```
123+
124+
</Block>
125+
<Block name="Combine">
126+
127+
```swift
128+
func listWebAuthNCredentials() -> AnyCancellable {
129+
Amplify.Publisher.create {
130+
try await Amplify.Auth.listWebAuthnCredentials(
131+
options: .init(pageSize: 5))
132+
}.sink {
133+
print("List WebAuthn Credential failed: \($0)")
134+
}
135+
receiveValue: { result in
136+
for credential in result.credentials {
137+
print("Credential ID: \(credential.credentialId)")
138+
print("Created At: \(credential.createdAt)")
139+
print("Relying Party Id: \(credential.relyingPartyId)")
140+
if let friendlyName = credential.friendlyName {
141+
print("Friendly name: \(friendlyName)")
142+
}
143+
}
144+
145+
if let nextToken = result.nextToken {
146+
// Fetch the next page
147+
}
148+
}
149+
}
150+
```
151+
152+
</Block>
153+
</BlockSwitcher>
154+
155+
</InlineFilter>
156+
157+
## Delete WebAuthN credentials
158+
159+
<InlineFilter filters={["angular", "javascript", "nextjs", "react", "react-native", "vue"]}>
160+
161+
{/* */}
162+
163+
</InlineFilter>
164+
<InlineFilter filters={["android"]}>
165+
166+
{/* */}
167+
168+
</InlineFilter>
169+
<InlineFilter filters={["swift"]}>
170+
171+
<BlockSwitcher>
172+
<Block name="Async/Await">
173+
174+
```swift
175+
func deleteWebAuthNCredentials(credentialId: String) async {
176+
do {
177+
try await Amplify.Auth.deleteWebAuthnCredential(credentialId: credentialId)
178+
print("WebAuthn credential was deleted")
179+
} catch {
180+
print("Delete WebAuthn Credential failed: \(error)")
181+
}
182+
}
183+
```
184+
185+
</Block>
186+
<Block name="Combine">
187+
188+
```swift
189+
func deleteWebAuthNCredentials(credentialId: String) -> AnyCancellable {
190+
Amplify.Publisher.create {
191+
try await Amplify.Auth.deleteWebAuthnCredential(credentialId: credentialId)
192+
}.sink {
193+
print("Delete WebAuthn Credential failed: \($0)")
194+
}
195+
receiveValue: { _ in
196+
print("WebAuthn credential was deleted")
197+
}
198+
}
199+
```
200+
201+
</Block>
202+
</BlockSwitcher>
203+
204+
</InlineFilter>

0 commit comments

Comments
 (0)