具有服务器端身份验证和 Cognito 的无服务器框架
Serverless Framework with server-side authentication and Cognito
我已经使用带有 APIG 的无服务器框架、DynamoDB 作为数据存储和用于用户身份验证的 Cognito 以及 Angular2 作为前端实现了各种 REST-APIs。服务器端的 Cognito 授权方可以轻松保护这些功能。缺点是我必须将 AWS SDK 集成到我的前端应用程序中,以便首先使用 Cognito 对用户进行身份验证 (signup/signin, ...)。我也可以使用 AWS_IAM 授权方,但在将请求发送到 API 网关之前,我还必须在客户端使用 AWS specific signature 签署所有请求。
现在我想知道是否有可能在服务器端保留身份验证和授权,这样我就可以为 signup/signin 使用像 JSON Web Tokens 这样的开放标准?这将使我也可以为其他开发人员开放我的 REST-API ,而无需强迫他们使用 Cognito。
我知道一种可能性是为我的 lambda 函数实现自定义授权器,但是没有任何稳定的东西可以使用 "out-of-the-box" 吗?我发现的大多数示例都在客户端使用 Cognito 或 IAM auth AWS 签名登录(例如 serverless-stack.com)。
奇怪的是,到目前为止我没有在网上找到任何关于此的有用信息,因为我认为这是 REST APIs 的典型用例。还是我对 API Gateway + Cognito 有概念上的误解?
在理解 AWS Cognito 的工作方式以及可用于实施身份验证和授权的选项方面,我遇到了同样的麻烦。不幸的是,没有 开箱即用的 方法可以满足您的要求。尽管如此,还是希望亚马逊能尽快推出一项功能。
基本上,有 3 个选项可用于实施身份验证。
- AWS_IAM
- Cognito 授权方
- 自定义授权方
AWS_IAM
除了身份验证之外,此方法还可用于使用 IAM 角色或 IAM 用户轻松实现授权。唯一的缺点是您需要发送使用 aws-signature-4 签名的请求,这不是我们在 Auth0 等 IDP 服务中看到的标准方式。
Cognito 授权方
此方法满足发送带有 API 请求的 JWT 令牌的预期。您可以在 Cognito 用户池中创建用户,然后使用它进行身份验证并生成 IdToken。但是,此方法只允许您对用户进行身份验证;授权需要在方法级别处理。
自定义授权方
这个方法可以用来写自己的认证授权方式。它还有助于消除在 API 方法中编写授权逻辑。理想的解决方案是使用 AWS Cognito 用户池对用户进行身份验证,然后为 IAM 角色生成策略文档以访问资源。
这是一个示例 。
另请记住,此解决方案将为您发出的每个请求调用一个额外的 lambda 函数。
您可以使用 Cognito Auth 来 Server-side。以下是步骤。
实施 Sign-up 和 Sign-in
在前端实现 Sign-up 表单,API 网关端点(例如 /register)使用 Lambda 接收 Sign-up 数据,这将创建用户在 Cognito 中使用 AWS SDK。详细参考检查 this link.
AWSCognito.config.region = 'us-east-1'; //This is required to derive the endpoint
var poolData = { UserPoolId : 'us-east-1_TcoKGbf7n',
ClientId : '4pe2usejqcdmhi0a25jp4b5sh3'
};
var userPool = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserPool(poolData);
var attributeList = [];
var dataEmail = {
Name : 'email',
Value : 'email@mydomain.com'
};
var dataPhoneNumber = {
Name : 'phone_number',
Value : '+15555555555'
};
var attributeEmail = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserAttribute(dataEmail);
var attributePhoneNumber = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserAttribute(dataPhoneNumber);
attributeList.push(attributeEmail);
attributeList.push(attributePhoneNumber);
userPool.signUp('username', 'password', attributeList, null, function(err, result){
if (err) {
alert(err);
return;
}
cognitoUser = result.user;
console.log('user name is ' + cognitoUser.getUsername());
});
通过创建前端和 API 网关端点(例如 /login)对 Sign-in 执行类似操作
var authenticationData = {
Username : 'username',
Password : 'password'
};
var authenticationDetails = new AWSCognito.CognitoIdentityServiceProvider.AuthenticationDetails(authenticationData);
var poolData = { UserPoolId : 'us-east-1_TcoKGbf7n',
ClientId : '4pe2usejqcdmhi0a25jp4b5sh3'
};
var userPool = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserPool(poolData);
var userData = {
Username : 'username',
Pool : userPool
};
var cognitoUser = new AWSCognito.CognitoIdentityServiceProvider.CognitoUser(userData);
cognitoUser.authenticateUser(authenticationDetails, {
onSuccess: function (result) {
console.log('access token + ' + result.getAccessToken().getJwtToken());
/* Use the idToken for Logins Map when Federating User Pools with Cognito Identity or when passing through an Authorization Header to an API Gateway Authorizer */
console.log('idToken + ' + result.idToken.jwtToken);
},
onFailure: function(err) {
alert(err);
},
});
从您的浏览器存储和发送 JWT,并在 API 网关进行验证。
- 从 Sign-in API 端点收到 JWT 后,您可以使用 HTML5 Localstorage、Sessionstorage 或客户端 Cookie 将其存储在用户浏览器本地.或者,如果您需要使用服务器端 Cookie,则需要有一个代理后端,它与 Web 应用程序保持 Session 状态并将其转换为 JWT 以调用 API 网关。
- 从 Web 浏览器(假设您的客户端直接调用 API 网关)设置一个名为 Authorization 的 HTTP header 并将 JWT 转发到 API 网关调用。
- 在 API 网关使用 Cognito 授权器作为授权令牌,它还将解析的用户身份转发给您的 Lambda。
注意:这里我有意避免了 IAM 授权,因为它需要 Web App JavaScripts 的一些额外工作才能在浏览器上实现 Signature 4 Signing,并且还需要经常刷新令牌,这是使用 AWS JavaScript SDK 很简单,但如果您需要自己实施它会变得复杂。
请看看这个here。
该示例演示了各种配置,包括自定义授权器、cognito、lambda、dynamoDB 等
我已经使用带有 APIG 的无服务器框架、DynamoDB 作为数据存储和用于用户身份验证的 Cognito 以及 Angular2 作为前端实现了各种 REST-APIs。服务器端的 Cognito 授权方可以轻松保护这些功能。缺点是我必须将 AWS SDK 集成到我的前端应用程序中,以便首先使用 Cognito 对用户进行身份验证 (signup/signin, ...)。我也可以使用 AWS_IAM 授权方,但在将请求发送到 API 网关之前,我还必须在客户端使用 AWS specific signature 签署所有请求。
现在我想知道是否有可能在服务器端保留身份验证和授权,这样我就可以为 signup/signin 使用像 JSON Web Tokens 这样的开放标准?这将使我也可以为其他开发人员开放我的 REST-API ,而无需强迫他们使用 Cognito。
我知道一种可能性是为我的 lambda 函数实现自定义授权器,但是没有任何稳定的东西可以使用 "out-of-the-box" 吗?我发现的大多数示例都在客户端使用 Cognito 或 IAM auth AWS 签名登录(例如 serverless-stack.com)。
奇怪的是,到目前为止我没有在网上找到任何关于此的有用信息,因为我认为这是 REST APIs 的典型用例。还是我对 API Gateway + Cognito 有概念上的误解?
在理解 AWS Cognito 的工作方式以及可用于实施身份验证和授权的选项方面,我遇到了同样的麻烦。不幸的是,没有 开箱即用的 方法可以满足您的要求。尽管如此,还是希望亚马逊能尽快推出一项功能。
基本上,有 3 个选项可用于实施身份验证。
- AWS_IAM
- Cognito 授权方
- 自定义授权方
AWS_IAM
除了身份验证之外,此方法还可用于使用 IAM 角色或 IAM 用户轻松实现授权。唯一的缺点是您需要发送使用 aws-signature-4 签名的请求,这不是我们在 Auth0 等 IDP 服务中看到的标准方式。
Cognito 授权方
此方法满足发送带有 API 请求的 JWT 令牌的预期。您可以在 Cognito 用户池中创建用户,然后使用它进行身份验证并生成 IdToken。但是,此方法只允许您对用户进行身份验证;授权需要在方法级别处理。
自定义授权方
这个方法可以用来写自己的认证授权方式。它还有助于消除在 API 方法中编写授权逻辑。理想的解决方案是使用 AWS Cognito 用户池对用户进行身份验证,然后为 IAM 角色生成策略文档以访问资源。
这是一个示例
您可以使用 Cognito Auth 来 Server-side。以下是步骤。
实施 Sign-up 和 Sign-in
在前端实现 Sign-up 表单,API 网关端点(例如 /register)使用 Lambda 接收 Sign-up 数据,这将创建用户在 Cognito 中使用 AWS SDK。详细参考检查 this link.
AWSCognito.config.region = 'us-east-1'; //This is required to derive the endpoint var poolData = { UserPoolId : 'us-east-1_TcoKGbf7n', ClientId : '4pe2usejqcdmhi0a25jp4b5sh3' }; var userPool = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserPool(poolData); var attributeList = []; var dataEmail = { Name : 'email', Value : 'email@mydomain.com' }; var dataPhoneNumber = { Name : 'phone_number', Value : '+15555555555' }; var attributeEmail = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserAttribute(dataEmail); var attributePhoneNumber = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserAttribute(dataPhoneNumber); attributeList.push(attributeEmail); attributeList.push(attributePhoneNumber); userPool.signUp('username', 'password', attributeList, null, function(err, result){ if (err) { alert(err); return; } cognitoUser = result.user; console.log('user name is ' + cognitoUser.getUsername()); });
通过创建前端和 API 网关端点(例如 /login)对 Sign-in 执行类似操作
var authenticationData = { Username : 'username', Password : 'password' }; var authenticationDetails = new AWSCognito.CognitoIdentityServiceProvider.AuthenticationDetails(authenticationData); var poolData = { UserPoolId : 'us-east-1_TcoKGbf7n', ClientId : '4pe2usejqcdmhi0a25jp4b5sh3' }; var userPool = new AWSCognito.CognitoIdentityServiceProvider.CognitoUserPool(poolData); var userData = { Username : 'username', Pool : userPool }; var cognitoUser = new AWSCognito.CognitoIdentityServiceProvider.CognitoUser(userData); cognitoUser.authenticateUser(authenticationDetails, { onSuccess: function (result) { console.log('access token + ' + result.getAccessToken().getJwtToken()); /* Use the idToken for Logins Map when Federating User Pools with Cognito Identity or when passing through an Authorization Header to an API Gateway Authorizer */ console.log('idToken + ' + result.idToken.jwtToken); }, onFailure: function(err) { alert(err); }, });
从您的浏览器存储和发送 JWT,并在 API 网关进行验证。
- 从 Sign-in API 端点收到 JWT 后,您可以使用 HTML5 Localstorage、Sessionstorage 或客户端 Cookie 将其存储在用户浏览器本地.或者,如果您需要使用服务器端 Cookie,则需要有一个代理后端,它与 Web 应用程序保持 Session 状态并将其转换为 JWT 以调用 API 网关。
- 从 Web 浏览器(假设您的客户端直接调用 API 网关)设置一个名为 Authorization 的 HTTP header 并将 JWT 转发到 API 网关调用。
- 在 API 网关使用 Cognito 授权器作为授权令牌,它还将解析的用户身份转发给您的 Lambda。
注意:这里我有意避免了 IAM 授权,因为它需要 Web App JavaScripts 的一些额外工作才能在浏览器上实现 Signature 4 Signing,并且还需要经常刷新令牌,这是使用 AWS JavaScript SDK 很简单,但如果您需要自己实施它会变得复杂。
请看看这个here。
该示例演示了各种配置,包括自定义授权器、cognito、lambda、dynamoDB 等