Amazon web services AWS Cognito授权代码在不使用托管UI的情况下授予流

Amazon web services AWS Cognito授权代码在不使用托管UI的情况下授予流,amazon-web-services,amazon-cognito,aws-cognito,Amazon Web Services,Amazon Cognito,Aws Cognito,在不使用托管UI的情况下使用AWS的Cognito,给定用户名和密码,我希望在不使用托管UI的情况下获得授权代码授权 这可能吗?我正在写我自己的注册、登录表格,但似乎找不到关于这个主题的文档 目前,我可以使用AWS.CognitoIdentityServiceProvider和initiateAuth函数来交换令牌的用户名密码,但我不想在重定向URL中返回这些令牌,我宁愿返回可以交换令牌的授权码授权 那么,如何使用initiateAuth接收授权码授权而不是令牌呢 更新:使用下面的正确答案,这就

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

这可能吗?我正在写我自己的注册、登录表格,但似乎找不到关于这个主题的文档

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

那么,如何使用initiateAuth接收授权码授权而不是令牌呢

更新:使用下面的正确答案,这就是我如何在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);
    });
});
const base64url=require('base64url');
const crypto=require('crypto');
const request=require('request');
const querystring=require('querystring');
函数generateCodeVerifierHash(代码验证程序){
返回crypto.createHmac('SHA256',代码验证程序)
.摘要(“base64”);
}
函数generateCodeVerifier(){
var text=“”;
var PROBIBLE=“ABCDEFGHIJKLMNOPQRSTUVXYZABCDFGHIJKLMNOPQRSTUVXYZ0123456789.`-”;
对于(变量i=0;i<64;i++)
text+=可能的.charAt(Math.floor(Math.random()*可能的.length));
返回base64url.encode(文本);
}
var CLIENT_ID=“您的客户ID”;
var CLIENT_SECRET=“您的客户机密”;
var响应\u TYPE=“代码”;
var REDIRECT_URI=encodeURIComponent(“您的重定向Url”);
var SCOPE=“openid”;
var AUTH_DOMAIN=“您的Cognito AUTH DOMAIN”;
var USERNAME=“用户的用户名”;
var PASSWORD=“用户密码”;
var代码挑战方法=“S256”;
//挑战
var code_verifier=generateCodeVerifier();
var code_challenge=generateCodeVerifierHash(代码验证器);
//从/oauth2/authorize端点获取CSRF令牌
var csrfRequestUrl=`https://${AUTH_DOMAIN}/oauth2/authorize?response_type=${response_type}&client_id=${client_id}&redirect_uri=${redirect_uri}&scope=${scope}&code_challenge_方法=${code_challenge方法}&code_challenge=${code_challenge;
//将CSRF令牌和用户名/密码发布到/login端点
var codeRequestUrl=`https://${AUTH_DOMAIN}/login?response_type=${response_type}&client_id=${client_id}&redirect_uri=${redirect_uri}`;
get(csrfRequestUrl,(err,res,body)=>{
var XSRFTOKEN=res.headers['set-cookie'].filter((header)=>header.substring(0,10)='XSRF-TOKEN')[0];
表格={
“_csrf”:${XSRFTOKEN.split(“;”)[0]。split(“=”)[1]}`,
'username':`${username}`,
'password':`${password}`,
}
var formData=querystring.stringify(表单);
var contentLength=formData.length;
请求({
标题:{
“内容长度”:contentLength,
“内容类型”:“应用程序/x-www-form-urlencoded”,
'Cookie':`${XSRFTOKEN}`,
},
uri:codeRequestUrl,
正文:formData,
方法:“发布”
},函数(错误、恢复、正文){
var authorizationCodeGrant=res.headers.location.split('=')[1];
console.log(authorizationCodeGrant);
});
});

使用initiateAuth和respondToAuthChallenge无法做到这一点,因为这只涉及对用户池的身份验证,最终结果是您将获得令牌

然而,完全可以通过代码和授权、令牌和登录端点交互。如果查看以下shell脚本代码,您将了解需要传递给端点的信息:

#!/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}"
#/usr/bin/env bash
#===============================================================================
#设置身份验证域
#===============================================================================
AUTH_DOMAIN=“MY-DOMAIN.AUTH.REGION.amazoncognito.com”
#===============================================================================
#身份验证代码/隐式授权,无PKCE,无客户端密码
#===============================================================================
##设置常数##
客户端\u ID=“用户\u池\u客户端\u ID”
响应类型=“代码”
#响应类型=“令牌”
重定向_URI=”https://example.com/"
SCOPE=“openid”
USERNAME=“testuser”
PASSWORD=“testpassword”
##从/oauth2/authorize端点获取CSRF令牌和登录URL##
curl_响应=”$(
curl-qv“https://${AUTH_DOMAIN}/oauth2/authorize?response_type=${response_type}&client_id=${client_id}&redirect_uri=${redirect_uri}&scope=${scope}”2>&1
)"
curl\u redirect=“$(printf”%s“$curl\u响应”\
|awk'/^<位置:/{
gsub(/\r/,“”)#删除回车符
打印$3;#打印重定向URL
}')"
csrf_token=“$(printf“%s”$curl_response”\
|awk'/^<设置Cookie:/{
gsub(/^XSRF-TOKEN=|$/,“”,$3);#删除cookie名称和分号
打印$3;#打印cookie值
}')"
##从/login端点获取身份验证代码或令牌##
curl_响应=”$(
curl-qv“$curl\u重定向”\
-H“Cookie:XSRF-TOKEN=${csrf_TOKEN};路径=/;安全;仅HttpOnly”\
-d“_csrf=${csrf_token}”\
-d“username=${username}”\
-d“password=${password}”2>&1
)"
curl\u redirect=“$(printf”%s“$curl\u响应”\
|awk'/^<位置:/{
gsub(/\r/,“”)#删除回车符
打印$3;#打印重定向URL
}')"
auth_code=“$(printf”%s“$curl\u重定向”\
|awk'{
sub(/.*code=/,“”)#在验证代码之前删除所有内容
打印;#打印身份验证代码
}')"
##从/oauth2/token端点获取令牌##
授权类型=“授权代码”
curl“https://${AUTH_DOMAIN}/oauth2/token”\
-d“grant_type=${grant_type}”\
-d“客户端id=${client\u id}”\
-d“代码=${auth_code}”\
-