不使用托管UI的AWS Cognito授权代码授予流程 [英] AWS Cognito Authorization code grant flow without using the hosted UI

查看:119
本文介绍了不使用托管UI的AWS Cognito授权代码授予流程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在不使用托管UI的情况下使用AWS的Cognito,给定用户名和密码的情况下,我希望在不使用托管ui的情况下获得授权码授予。

Using AWS's Cognito without the hosted UI, given a username, and password I would like to receive an Authorization code grant without using the hosted ui.

这可能吗?我正在编写自己的注册,登录表单,但似乎找不到有关此主题的文档。

Is this possible? I am writing my own sign up, log in forms but cannot seem to find documentation on this subject.

当前,我可以使用AWS.CognitoIdentityServiceProvider和initializeAuth函数来交换用户名令牌的密码,但是我不想在重定向URL中返回这些令牌,我宁愿返回可以交换令牌的授权码授予。

Currently I can use AWS.CognitoIdentityServiceProvider and the initiateAuth function to exchange username password for tokens, but I do not want to return those tokens in the redirect URL, I would rather return an authorization code grant that can be exchanged for tokens.

更新:使用下面的正确答案,这就是我最终在节点中执行此操作的方式。

UPDATE: Using the correct answer below, this is how I ended up doing it in node.

const base64url = require('base64url');
const crypto = require('crypto');
const request = require('request');
const querystring = require ('querystring');

function generateCodeVerifierHash(code_verifier) {
  return crypto.createHmac('SHA256', code_verifier)
  .digest('base64');
}

function generateCodeVerifier() {
  var text = "";
  var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._`-";

  for (var i = 0; i < 64; i++)
    text += possible.charAt(Math.floor(Math.random() * possible.length));

  return base64url.encode(text);
}

var CLIENT_ID="Your Client Id";
var CLIENT_SECRET="Your Client Secret";
var RESPONSE_TYPE="code";
var REDIRECT_URI= encodeURIComponent("Your Redirect Url");
var SCOPE="openid";
var AUTH_DOMAIN= "Your Cognito Auth Domain";
var USERNAME="User's Username";
var PASSWORD="User's Password";
var CODE_CHALLENGE_METHOD="S256";

// Challenge
var code_verifier = generateCodeVerifier();
var code_challenge = generateCodeVerifierHash(code_verifier);

// Get CSRF token from /oauth2/authorize endpoint
var csrfRequestUrl = `https://${AUTH_DOMAIN}/oauth2/authorize?response_type=${RESPONSE_TYPE}&client_id=${CLIENT_ID}&redirect_uri=${REDIRECT_URI}&scope=${SCOPE}&code_challenge_method=${CODE_CHALLENGE_METHOD}&code_challenge=${code_challenge}`;
// Post CSRF Token and username/password to /login endpoint
var codeRequestUrl = `https://${AUTH_DOMAIN}/login?response_type=${RESPONSE_TYPE}&client_id=${CLIENT_ID}&redirect_uri=${REDIRECT_URI}`;

request.get(csrfRequestUrl, (err, res, body) => {
    var XSRFTOKEN = res.headers['set-cookie'].filter( (header) => header.substring(0,10) == 'XSRF-TOKEN')[0];

    form = {
      '_csrf': `${XSRFTOKEN.split(';')[0].split('=')[1]}`,
      'username': `${USERNAME}`,
      'password': `${PASSWORD}`,
    }

    var formData = querystring.stringify(form);
    var contentLength = formData.length;

    request({
      headers: {
        'Content-Length': contentLength,
        'Content-Type': 'application/x-www-form-urlencoded',
        'Cookie': `${XSRFTOKEN}`,
      },
      uri: codeRequestUrl,
      body: formData,
      method: 'POST'
    }, function (err, res, body) {
      var authorizationCodeGrant = res.headers.location.split('=')[1];
      console.log(authorizationCodeGrant);
    });
});


推荐答案

没有办法通过使用initializeAuth和responseToAuthChallenge,因为这只涉及对用户池的身份验证,最终结果是您将获得令牌。

There is no way to do that by using initiateAuth and respondToAuthChallenge since that involves just authentication against your user pool and the end result will be that you will get tokens.

但是,完全有可能通过代码与授权,令牌和登录端点进行交互。如果您看下面的shell脚本代码,您将对需要传递到端点的信息有所了解:

However, it is totally possible to interact with the authorize, token, and login endpoints through code. If you have a look at the following shell script code, you will have an idea of the information that needs to be passed to the endpoints:

#!/usr/bin/env bash

#===============================================================================
# SET AUTH DOMAIN
#===============================================================================
AUTH_DOMAIN="MY-DOMAIN.auth.REGION.amazoncognito.com"

#===============================================================================
# AUTH CODE/IMPLICIT GRANTS, WITHOUT PKCE, WITHOUT CLIENT SECRET
#===============================================================================

## Set constants ##
CLIENT_ID="USER_POOL_CLIENT_ID"
RESPONSE_TYPE="code"
#RESPONSE_TYPE="token"
REDIRECT_URI="https://example.com/"
SCOPE="openid"

USERNAME="testuser"
PASSWORD="testpassword"

## Get CSRF token and LOGIN URL from /oauth2/authorize endpoint ##
curl_response="$(
    curl -qv "https://${AUTH_DOMAIN}/oauth2/authorize?response_type=${RESPONSE_TYPE}&client_id=${CLIENT_ID}&redirect_uri=${REDIRECT_URI}&scope=${SCOPE}" 2>&1
)"
curl_redirect="$(printf "%s" "$curl_response" \
                    | awk '/^< Location: / {
                        gsub(/\r/, ""); # Remove carriage returns
                        print $3;       # Print redirect URL
                    }')"
csrf_token="$(printf "%s" "$curl_response" \
                   | awk '/^< Set-Cookie:/ {
                       gsub(/^XSRF-TOKEN=|;$/, "", $3); # Remove cookie name and semi-colon
                       print $3;                        # Print cookie value
                    }')"

## Get auth code or tokens from /login endpoint ##
curl_response="$(
    curl -qv "$curl_redirect" \
        -H "Cookie: XSRF-TOKEN=${csrf_token}; Path=/; Secure; HttpOnly" \
        -d "_csrf=${csrf_token}" \
        -d "username=${USERNAME}" \
        -d "password=${PASSWORD}" 2>&1
)"
curl_redirect="$(printf "%s" "$curl_response" \
                    | awk '/^< Location: / {
                        gsub(/\r/, ""); # Remove carriage returns
                        print $3;       # Print redirect URL
                    }')"
auth_code="$(printf "%s" "$curl_redirect" \
                | awk '{
                    sub(/.*code=/, ""); # Remove everything before auth code
                    print;              # Print auth code
                }')"

## Get tokens from /oauth2/token endpoint ##
GRANT_TYPE="authorization_code"
curl "https://${AUTH_DOMAIN}/oauth2/token" \
    -d "grant_type=${GRANT_TYPE}" \
    -d "client_id=${CLIENT_ID}" \
    -d "code=${auth_code}" \
    -d "redirect_uri=${REDIRECT_URI}"

#===============================================================================
# AUTH CODE/IMPLICIT GRANTS, WITH PKCE, WITH CLIENT SECRET
#===============================================================================

## Set constants ##
CLIENT_ID="USER_POOL_CLIENT_ID"
CLIENT_SECRET="USER_POOL_CLIENT_SECRET"
RESPONSE_TYPE="code"
#RESPONSE_TYPE="token"
REDIRECT_URI="https://example.com/"
SCOPE="openid"

USERNAME="testuser"
PASSWORD="testpassword"

## Create a code_verifier and code_challenge ##
CODE_CHALLENGE_METHOD="S256"
# code_verifier = random, 64-char string consisting of chars between letters,
#                 numbers, periods, underscores, tildes, or hyphens; the string
#                 is then base64-url encoded
code_verifier="$(cat /dev/urandom \
                    | tr -dc 'a-zA-Z0-9._~-' \
                    | fold -w 64 \
                    | head -n 1 \
                    | base64 \
                    | tr '+/' '-_' \
                    | tr -d '='
                )"
# code_challenge = SHA-256 hash of the code_verifier; it is then base64-url
#                  encoded
code_challenge="$(printf "$code_verifier" \
                    | openssl dgst -sha256 -binary \
                    | base64 \
                    | tr '+/' '-_' \
                    | tr -d '='
                )"

## Get CSRF token from /oauth2/authorize endpoint ##
curl_response="$(
    curl -qv "https://${AUTH_DOMAIN}/oauth2/authorize?response_type=${RESPONSE_TYPE}&client_id=${CLIENT_ID}&redirect_uri=${REDIRECT_URI}&scope=${SCOPE}&code_challenge_method=${CODE_CHALLENGE_METHOD}&code_challenge=${code_challenge}" 2>&1
)"
curl_redirect="$(printf "%s" "$curl_response" \
                    | awk '/^< Location: / {
                        gsub(/\r/, ""); # Remove carriage returns
                        print $3;       # Print redirect URL
                    }')"
csrf_token="$(printf "%s" "$curl_response" \
                | awk '/^< Set-Cookie:/ {
                    gsub(/^XSRF-TOKEN=|;$/, "", $3); # Remove cookie name and semi-colon
                    print $3;                        # Print cookie value
                }')"

## Get auth code or tokens from /login endpoint ##
curl_response="$(
    curl -qv "$curl_redirect" \
        -H "Cookie: XSRF-TOKEN=${csrf_token}; Path=/; Secure; HttpOnly" \
        -d "_csrf=${csrf_token}" \
        -d "username=${USERNAME}" \
        -d "password=${PASSWORD}" 2>&1
)"
curl_redirect="$(printf "%s" "$curl_response" \
                    | awk '/^< Location: / {
                        gsub(/\r/, ""); # Remove carriage returns
                        print $3;       # Print redirect URL
                    }'
                )"
auth_code="$(printf "%s" "$curl_redirect" \
                | awk '{
                    sub(/.*code=/, ""); # Remove everything before auth code
                    print;              # Print auth code
                }')"

## Get tokens from /oauth2/token endpoint ##
authorization="$(printf "${CLIENT_ID}:${CLIENT_SECRET}" \
                    | base64 \
                    | tr -d "\n" # Remove line feed
                )"
GRANT_TYPE="authorization_code"
curl "https://${AUTH_DOMAIN}/oauth2/token" \
    -H "Authorization: Basic ${authorization}" \
    -d "grant_type=${GRANT_TYPE}" \
    -d "client_id=${CLIENT_ID}" \
    -d "code=${auth_code}" \
    -d "redirect_uri=${REDIRECT_URI}" \
    -d "code_verifier=${code_verifier}"

#===============================================================================
# CLIENT CREDENTIALS GRANT
#===============================================================================

## Set constants ##
CLIENT_ID="USER_POOL_CLIENT_ID"
CLIENT_SECRET="USER_POOL_CLIENT_SECRET"
GRANT_TYPE="client_credentials"

## Get access token from /oauth2/token endpoint ##
authorization="$(printf "${CLIENT_ID}:${CLIENT_SECRET}" \
                    | base64 \
                    | tr -d "\n" # Remove line feed
                )"
curl "https://${AUTH_DOMAIN}/oauth2/token" \
    -H "Authorization: Basic ${authorization}" \
    -d "grant_type=${GRANT_TYPE}"

#===============================================================================
# LOGOUT
#===============================================================================

## Set constants ##
CLIENT_ID="USER_POOL_CLIENT_ID"
REDIRECT_URI="https://example.com/"

## Hit /logout endpoint ##
curl -v "https://${AUTH_DOMAIN}/logout?client_id=${CLIENT_ID}&logout_uri=${REDIRECT_URI}"

这篇关于不使用托管UI的AWS Cognito授权代码授予流程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆