具有服务器端身份验证和Cognito的无服务器框架

时间:2017-08-11 09:21:31

标签: rest authentication aws-lambda amazon-cognito serverless-framework

我已经使用带APIG的无服务器框架,DynamoDB作为数据存储以及使用Angular2作为前端进行用户身份验证的Cognito实现了各种REST-API。服务器端的Cognito授权人可以轻松保护这些功能。缺点是我必须在我的前端应用程序中集成AWS SDK才能首先使用Cognito对用户进行身份验证(注册/登录,...)。我也可以使用AWS_IAM授权程序,但在将请求发送到API网关之前,我还必须使用AWS specific signature在客户端对所有请求进行签名。

现在我想知道是否有可能在服务器端保留身份验证和授权,所以我可以使用像JSON Web Tokens这样的开放标准进行注册/签名?这样我就可以为其他开发人员打开我的REST-API ,而不必强迫他们使用Cognito

我知道有一种可能性是为我的lambda函数实现一个自定义授权器,但是没有任何稳定的东西,可以用“开箱即用”吗?我发现的大多数示例都是在客户端使用Cognito或IAM auth AWS签名(例如serverless-stack.com)。

很奇怪我到目前为止在网上找不到任何有用的信息,因为我认为这是REST API的典型用例。或者我对API Gateway + Cognito存在概念上的误解?

3 个答案:

答案 0 :(得分:3)

我在理解AWS Cognito如何工作的方式以及可用于实现身份验证的选项方面遇到了同样的麻烦。授权。不幸的是,没有开箱即用方法可以满足您的需求。尽管如此,我们希望亚马逊能够很快推出一项功能。

基本上,有3个选项可用于实现身份验证。

  1. AWS_IAM
  2. Cognito Authorizer
  3. 自定义授权商
  4. AWS_IAM

    除了身份验证之外,此方法还可用于轻松地使用IAM角色或IAM用户实施授权。唯一的缺点是你需要发送一个用 aws-signature-4 签名的请求,这不是我们在Auth0等IDP服务中看到的标准方式。

    Cognito Authorizer

    此方法满足发送带有API请求的JWT令牌的期望。您可以在Cognito User Pool中创建用户,然后使用它来进行身份验证并生成IdToken。但是,此方法仅允许您对用户进行身份验证;授权需要在方法级别处理。

    自定义授权程序

    此方法可用于编写自己的身份验证和授权方式。此外,它有助于消除API方法中的写入授权逻辑。理想的解决方案是使用AWS Cognito用户池对用户进行身份验证,然后为IAM角色生成策略文档以访问资源。 这是一个示例AWS cognito userpools JavaScript SDK get user's policy documents。 另请注意,此解决方案将为您发出的每个请求调用额外的lambda函数。

答案 1 :(得分:2)

您可以将Cognito Auth用于服务器端。以下是步骤。

实施注册和登录

  • 使用Lambda接收注册数据,在前端和API网关端点(例如/ register)中实施注册表单,注册数据将使用AWS SDK在Cognito中创建用户。有关详细参考,请查看this链接。

    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网关端点(例如/登录)

    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网关验证。

  • 从登录API端点接收JWT后,您可以使用HTML5 Localstorage,Sessionstorage或Client Side Cookie将其存储在用户浏览器的本地。可选地,如果您需要使用服务器端Cookie,则需要具有代理后端,该后端使用Web应用程序保持会话状态并将其转换为JWT以调用API网关。
  • 从Web浏览器(假设您的客户端直接调用API网关)设置一个名为Authorization的HTTP标头,并将JWT转发给API网关调用。
  • 在API网关中,使用Cognito Authorizer作为授权令牌,它还会将解析的用户身份转发给您的Lambdas。

注意:这里我有目的地避免了IAM授权,因为它需要Web App JavaScripts的一些额外工作来在浏览器中实现Signature 4 Signing,并且还需要经常刷新令牌,这对于AWS JavaScript SDK来说是直截了当的,但是如果你需要自己实现它,就会变得复杂。

答案 2 :(得分:1)

请查看此Caching and dynamic pricing – upcoming changes to the get_variation_prices method

该示例演示了各种配置,包括自定义授权程序,cognito,lambda,dynamoDB等。