分享我的发现已经很晚了,但我会为其他在 AWS 身份验证和授权方面遇到相同问题的人写下方法。
首先,请注意以下要求无法通过 AWS Cognito 实现。换句话说,我们必须使用 AWS SDK(据我了解)来获得 AWS 凭证。
我的客户是一些服务,他们像以下请求一样调用这些 Rest API:(它是用 Javascript 编写的,但他们可以使用任何其他编程语言,但不能使用 AWS SDK)
让我们看看 AWS Cognito 及其组件的描述,基于 AWS 文档:
Amazon Cognito 提供身份验证、授权和用户
管理您的网络和移动应用程序。您的用户可以登录
直接使用用户名和密码,或通过第三方等
如 Facebook、亚马逊、谷歌或苹果。
Amazon Cognito 的两个主要组件是用户池和身份
池。用户池是提供注册和
应用程序用户的登录选项。身份池使您能够授予
您的用户可以访问其他 AWS 服务。
所以为了澄清上面的解释,我们可以使用用户池组件来提供身份验证和身份池,以提供对 AWS 服务的访问和最终授权。
您应该注意的是,如果不使用身份池,AWS 不支持授权。
由于有一篇关于如何实现身份验证和授权的信息丰富的文章 - 链接如下 - 我只是简要介绍了相关场景,我发现在完成实施步骤之前了解这些内容很有用。
http://interworks.com.mk/amazon-cognito-and-api-gateway-aws-iam-authorization/
-
用户应使用用户池对自己进行身份验证。您的应用用户可以直接通过用户池登录,也可以通过第三方身份提供商 (IdP) 联合登录。登录过程可以通过 Web 或 API 进行。
-
身份验证成功后,您的 Web 或移动应用程序将从 Amazon Cognito 接收经过身份验证的用户的用户池令牌。
-
您应该使用这些令牌来检索允许您的应用访问其他 AWS 服务的 AWS 凭证。
-
您可以使用收到的凭证发送访问 AWS 服务的请求,在我们的示例中为 API Gateway。向 AWS API Gateway 发送请求有两种选择。第一个使用 AWS SDK,第二个使用其他库,例如 Axios。关键是如果您手动发送请求(例如通过 axios),您应该在发送之前签署请求。但如果您使用 AWS SDK,AWS SDK 将自行处理签名过程,您无需执行任何操作。
有一个示例代码在 NodeJs 中实现了这个场景。在这个示例中,我们使用 Axios 库将请求发送到 API Gateway。
const AWS = require("aws-sdk");
const crypto = require("crypto");
const aws4 = require("aws4");
const axios = require("axios");
// Client information
const CLIENT_SECRET = "######";
const CLIENT_ID = "####";
const USER_POOL_ID = "####";
const IDENTITY_POOL_ID = "####";
const COGNITO_AUTH_PROVIDER =
"cognito-idp.<REGION>.amazonaws.com/<USER_POOL_ID>";
// AWS config
AWS.config.region = "XXXX";
// If client_secret is enabled in user pool, client_secret should be converted to a Base64 encoded value called HASH_SECRET
const createHashSecret = (username) => {
return crypto
.createHmac("SHA256", CLIENT_SECRET)
.update(`${username}${CLIENT_ID}`)
.digest("base64");
};
// User information
const userInfo = {
username: "###",
password: "###",
};
const userPoolData = {
UserPoolId: USER_POOL_ID,
ClientId: CLIENT_ID,
};
/**
* Add user credential to AWS request sent by HTTP
* By Signature Version 4
*/
const generateApiGatewayRequest = (credentials, requestParams) => {
const { url, hostname, path, method } = requestParams;
const options = {
service: "execute-api",
region: AWS.config.region,
url,
hostname,
path,
method,
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
};
// Sign the request by some metadata
return aws4.sign(options, credentials);
};
// Create an authentication client to connect to user pool
const cognitoIdentityServiceProvider = new AWS.CognitoIdentityServiceProvider(
userPoolData
);
// Request to authenticate a user
cognitoIdentityServiceProvider.initiateAuth({
AuthFlow: "USER_PASSWORD_AUTH",
ClientId: CLIENT_ID,
AuthParameters: {
USERNAME: userInfo.username,
PASSWORD: userInfo.password,
SECRET_HASH: createHashSecret(userInfo.username),
},
}, function (err, data) {
if (err) {
// Something wrong has happened, like invalid user info, invalid pool and client info, ...
// The error object contains message, code, time, requestId, statusCode, ...
console.log(err);
} else {
// id token, access token and refresh token have been created.
console.log(data.AuthenticationResult);
// Request for authorization with Identity pool
AWS.config.credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: IDENTITY_POOL_ID,
Logins: {
[COGNITO_AUTH_PROVIDER]: data.AuthenticationResult.IdToken,
},
});
// Check if the request for AWS credential has been done successfully
AWS.config.credentials.get(function (err) {
if (err) {
// There is no received credential
console.log(err);
} else {
// The logged-in user now has a temporary credential to ask for AWS services such as Api Gateway
// The credential includes accessKeyId, secretAccessKey, sessionToken, etc
var userCredential = AWS.config.credentials;
// Request protected resources (Api Gateway)
axios(
generateApiGatewayRequest(userCredential, {
url:
"https://XXX.execute-api.us-east-1.amazonaws.com/main/tasks",
hostname: "XXX.execute-api.us-east-1.amazonaws.com",
path: "/main/tasks",
method: "GET",
})
)
.then((result) => {
// Request's been done successfully
console.log(result);
})
.catch((error) => {
// The error could be either resource errors like Bad Request or Forbidden as the user doesn't have the permission to access the resource
console.log(error);
});
}
});
}
});
有关详细信息,请参阅上面链接的文章。但是,如果仍有一些模棱两可的部分,请随时在下面发表评论。