awslabs / aws-api-gateway-developer-portal

A Serverless Developer Portal for easily publishing and cataloging APIs
Apache License 2.0
924 stars 399 forks source link

Handling Authorization #508

Open talipini opened 2 years ago

talipini commented 2 years ago

How do you facilitate the end user getting access to IdToken or AccessToken, if the API is secured by Cognito Pool Authorizer? Is there a different mechanism for securing the API along the api-key? Appreciate any ideas on how to secure the API while keeping it simple for the end user to use it. Thanks

tej-rana commented 2 years ago

@talipini What did you end up doing? I see that we can import new OpenAPI 3/2 definition manually. I can manually extract the IdToken and make calls in Postman for testing. There is a dashboard area that shows the usage graph and api key. Maybe displaying the id token there could be the way to go. It is located in Local Storage.

tej-rana commented 2 years ago

This only addresses Authentication. @talipini I created an endpoint /auth POST request to call a lambda function that accepts username and password. You must enable USER_PASSWORD_AUTH in cognito's app client for this to work.

Here is excerpt of the lambda function.

Install npm package amazon-cognito-identity-js first.

const AmazonCognitoIdentity = require('amazon-cognito-identity-js');
const poolData = {    
    UserPoolId : 'POOL_ID',    
    ClientId : 'CLIENT ID of APP'
}; 

const userPool = new AmazonCognitoIdentity.CognitoUserPool(poolData);

exports.handler = function(event, context, callback) {
    let username = '';
    let password = '';

    if (event.body) {
        let body = JSON.parse(event.body)
        if (body.password) 
            password = body.password;
        if (body.username) 
            username = body.username;
    }

    login(event.username, event.password, callback);

    login = function(user, pass, callback) {

    var authenticationDetails = new AmazonCognitoIdentity.AuthenticationDetails({
        Username : user,
        Password : pass,
    });

    var userData = {
        Username : user,
        Pool : userPool
    };
    var cognitoUser = new AmazonCognitoIdentity.CognitoUser(userData);
    let response = {
        statusCode: 200,        
        body: null
    };

    cognitoUser.authenticateUser(authenticationDetails, {
        onSuccess: function (result) {
            let idToken = result.getIdToken().getJwtToken();
            response.body = {
                token: idToken
            }
            callback(null, response);         
        },
        onFailure: function(err) {
            console.log(err);

            response.body = err;
            response.statusCode = 401;
            callback(null, response);
        },
    });
}

The developers consuming the api can use amplify in their apps to do this. But to be able to test it at least (sandbox environment for example) they could use /auth. Also if they have their own api, this makes it easier.