AWS Cognito 中的用户需要 MFA 时的身份验证流程
Flow for authentication when MFA required for user in AWS Cognito
我正在尝试将用于用户身份验证的 MFA 添加到 AWS Cognito 中用于设备管理的现有解决方案(内置于 Angular)。
我无法弄清楚如何从用户体验的角度很好地处理这个特定的响应。它实际上感觉很破碎,所以如果其他人在这里遇到痛点,我会很高兴。
参见 Use Case 23. 示例实现,我的如下:
authenticate(username: string, password: string): Observable<any> {
// init cognitoUser here
return new Observable((observer) => {
cognitoUser.authenticateUser(authenticationDetails, {
onSuccess: (result: any) => {},
onFailure: (err: Error) => {},
mfaRequired: (codeDeliveryDetails: any) => {
// SMS has just been sent automatically
// and it needs to be confirmed within this scope
// The example linked requests the code via `confirm()`
// which is awful UX...and since this is a service
// probably non-compliant with best practice
// However, without this `confirm` at this point in
// time, we have no confirmationCode below
cognitoUser.sendMFACode(confirmationCode, {
onSuccess: (result) => {
observer.next(result);
observer.complete();
}, onFailure: (err: Error) => {
observer.error(err);
observer.complete();
}
});
}
});
});
}
预计:
- 如果用户验证成功但没有通过 MFA 添加此设备,我们可以管理重定向到适当的确认代码表单页面并手动触发
sendMFACode
功能(可能通过某种有限会话?)
Issue/s:
- 我们没有会话,所以我们无法询问用户在此登录屏幕之外自动发送的 MFA 代码...赶上 22?
- 在登录表单中添加另一个 show/hide 字段不起作用,因为它会多次点击
sendMfaCode
函数,导致发送多个 SMS 代码。
有没有人幸运地走出了这个流程?
虽然我确信非常有才华的人在 amazon-cognito-identity-js API 上工作,但它的设计很糟糕。这就是为什么它被贬低的原因。我个人的建议是迁移到 Amplify,这样我就不那么生气了。
使用 Amplify 你可以做到这些。
import Amplify from 'aws-amplify'
import Auth from '@aws-amplify/auth'
let mfaRequired = false
Amplify.configure({
Auth: {
userPoolWebClientId: '',
userPoolId: ''
}
})
const logUserIn = (user) => {
// Go forth and be happy
}
// Run me on your login form's submit event
const login = async (username, password) => {
const user = await Auth.signIn(username, password)
if (user.challengeName === 'SMS_MFA') {
// Change UI to show MFA Code input
mfaRequired = true
return
}
return logUserIn(user)
}
// Run me when the user submits theire MFA code
const senfMfaCode = async (mfaCode) => {
const user = await Auth.confirmSignIn(mfaCode)
return logUserIn(user)
}
但是,如果出于某些可悲的原因您需要继续使用 amazon-cognito-identity-js,请不要担心。我找到你了。
只需将 cognitoUser
对象存储在回调之外。该文档有点误导,因为它只显示了自包含的示例,但没有理由不能在需要 MFA 时通知您的 UI,然后稍后调用 cognitoUser.sendMFACode()
。
请记住,文档显示将 this
传递给 sendMFACode()
以进行范围界定(这很糟糕),但您可以将回调声明为变量并在 [=16] 之间共享=] 和 sendMFACode()
函数(或任意数量的函数)。
import { CognitoUserPool, AuthenticationDetails, CognitoUser } from 'amazon-cognito-identity-js'
export let mfaRequired = false
export let cognitoUser = null
export const cognitoCallbacks = {
mfaRequired () {
// Implement you functionality to show UI for MFA form
mfaRequired = true
},
onSuccess (response) {
// Dance for joy the code gods be glorious.
},
onFailure () {
// Cry.
}
}
export const logUserIn = payload => {
cognitoUser = new CognitoUser({
Username: 'Matt Damon',
Pool: new CognitoUserPool({
UserPoolId: '',
ClientId: ''
})
})
return cognitoUser.authenticateUser(new AuthenticationDetails(payload), cognitoCallbacks)
}
export const sendMfaCode = MFACode => {
cognitoUser.sendMFACode(MFACode, cognitoCallbacks)
}
这是一个超级基本的实现,除此之外你还可以,
- 只需覆盖外部模块中的
mfaRequired
函数即可为所欲为。
- 将整个内容封装在一个 pub/sub 插件中并订阅事件。
希望对您有所帮助!
我正在尝试将用于用户身份验证的 MFA 添加到 AWS Cognito 中用于设备管理的现有解决方案(内置于 Angular)。
我无法弄清楚如何从用户体验的角度很好地处理这个特定的响应。它实际上感觉很破碎,所以如果其他人在这里遇到痛点,我会很高兴。
参见 Use Case 23. 示例实现,我的如下:
authenticate(username: string, password: string): Observable<any> {
// init cognitoUser here
return new Observable((observer) => {
cognitoUser.authenticateUser(authenticationDetails, {
onSuccess: (result: any) => {},
onFailure: (err: Error) => {},
mfaRequired: (codeDeliveryDetails: any) => {
// SMS has just been sent automatically
// and it needs to be confirmed within this scope
// The example linked requests the code via `confirm()`
// which is awful UX...and since this is a service
// probably non-compliant with best practice
// However, without this `confirm` at this point in
// time, we have no confirmationCode below
cognitoUser.sendMFACode(confirmationCode, {
onSuccess: (result) => {
observer.next(result);
observer.complete();
}, onFailure: (err: Error) => {
observer.error(err);
observer.complete();
}
});
}
});
});
}
预计:
- 如果用户验证成功但没有通过 MFA 添加此设备,我们可以管理重定向到适当的确认代码表单页面并手动触发
sendMFACode
功能(可能通过某种有限会话?)
Issue/s:
- 我们没有会话,所以我们无法询问用户在此登录屏幕之外自动发送的 MFA 代码...赶上 22?
- 在登录表单中添加另一个 show/hide 字段不起作用,因为它会多次点击
sendMfaCode
函数,导致发送多个 SMS 代码。
有没有人幸运地走出了这个流程?
虽然我确信非常有才华的人在 amazon-cognito-identity-js API 上工作,但它的设计很糟糕。这就是为什么它被贬低的原因。我个人的建议是迁移到 Amplify,这样我就不那么生气了。
使用 Amplify 你可以做到这些。
import Amplify from 'aws-amplify'
import Auth from '@aws-amplify/auth'
let mfaRequired = false
Amplify.configure({
Auth: {
userPoolWebClientId: '',
userPoolId: ''
}
})
const logUserIn = (user) => {
// Go forth and be happy
}
// Run me on your login form's submit event
const login = async (username, password) => {
const user = await Auth.signIn(username, password)
if (user.challengeName === 'SMS_MFA') {
// Change UI to show MFA Code input
mfaRequired = true
return
}
return logUserIn(user)
}
// Run me when the user submits theire MFA code
const senfMfaCode = async (mfaCode) => {
const user = await Auth.confirmSignIn(mfaCode)
return logUserIn(user)
}
但是,如果出于某些可悲的原因您需要继续使用 amazon-cognito-identity-js,请不要担心。我找到你了。
只需将 cognitoUser
对象存储在回调之外。该文档有点误导,因为它只显示了自包含的示例,但没有理由不能在需要 MFA 时通知您的 UI,然后稍后调用 cognitoUser.sendMFACode()
。
请记住,文档显示将 this
传递给 sendMFACode()
以进行范围界定(这很糟糕),但您可以将回调声明为变量并在 [=16] 之间共享=] 和 sendMFACode()
函数(或任意数量的函数)。
import { CognitoUserPool, AuthenticationDetails, CognitoUser } from 'amazon-cognito-identity-js'
export let mfaRequired = false
export let cognitoUser = null
export const cognitoCallbacks = {
mfaRequired () {
// Implement you functionality to show UI for MFA form
mfaRequired = true
},
onSuccess (response) {
// Dance for joy the code gods be glorious.
},
onFailure () {
// Cry.
}
}
export const logUserIn = payload => {
cognitoUser = new CognitoUser({
Username: 'Matt Damon',
Pool: new CognitoUserPool({
UserPoolId: '',
ClientId: ''
})
})
return cognitoUser.authenticateUser(new AuthenticationDetails(payload), cognitoCallbacks)
}
export const sendMfaCode = MFACode => {
cognitoUser.sendMFACode(MFACode, cognitoCallbacks)
}
这是一个超级基本的实现,除此之外你还可以,
- 只需覆盖外部模块中的
mfaRequired
函数即可为所欲为。 - 将整个内容封装在一个 pub/sub 插件中并订阅事件。
希望对您有所帮助!