我已经构建了iOS和Android应用程序。这些应用使用Cognito用户池来允许对API网关进行公开身份验证和未经身份验证的访问。
我正试图阻止第三方应用程序访问此API。我只希望获得授权访问API的应用。可以将对APIG的访问权限限制为仅我的应用程序吗?
Cognito在用户池的设置中提供了App Client ID和App Client Secret的概念。这是将Cognito登录限制为列入白名单的客户端/应用程序的首选机制吗? docs对于此配置的目的或使这些密钥在野外保持安全的最佳做法的说明很少。
是否有其他方法可以实现我正在尝试的目标?这个目标甚至有可能实现吗?我相信可以对这些密钥进行逆向工程,或者可以通过网络嗅探器发现它们。
我是API安全的新手,因此您的见解受到赞赏。
答案 0 :(得分:1)
看看Cognito Identity。 Cognito Federated Identity Pools
提供经过身份验证和未经身份验证的访问。这会很长,所以请忍受我。 (我的代码示例在yaml或JS中使用cloudformation)。我假设您已经创建了user pool
和app client
。您将需要那些来创建identity pool
。我还将假设您的用户池allowed oauth flows
设置为implicit grant
,而allowed oauth scope
是openid
。这是获得用于创建id_token
的{{1}}所必需的。
使用您的federated identity
作为经过身份验证的提供者来创建cognito identity pool
。同样的样本CFN Yaml
cognito user pool
现在将您已认证和未认证的角色附加到您刚创建的AccIdenAdminPool:
Type: "AWS::Cognito::IdentityPool"
Properties:
IdentityPoolName: <identity pool name as input>
AllowUnauthenticatedIdentities: true
CognitoIdentityProviders:
- ClientId: <your app client id>
ProviderName: "cognito-idp.us-east-1.amazonaws.com/<your user pool id>"
ServerSideTokenCheck: true
上。样本JS代码-
identity pool
将API网关身份验证从module.exports.attachRole = (event, context, callback) => {
console.log(JSON.stringify(event)); // successful response
let params = {
IdentityPoolId: event.identityPoolId, /* required */
Roles: {
/* required */
'authenticated': <auth role arn>,
'unauthenticated': <unauth role arn>
},
};
cognitoidentity.setIdentityPoolRoles(params, function (err, data) {
if (err) {
console.log(err, err.stack);
}
else {
console.log("success"); // successful response
}
});
}
更改为Cognito user pool authorizer
。这是必须的。如果由于某种原因您不能执行此操作,则需要找出其他方法来关闭未经授权的API访问。
对于身份验证访问,请使用AWS_IAM
(成功登录后收到),身份池ID和用户池ID来获取id_token
。示例代码-
CognitoIdentityCredentials
使用此function getAccessToken(idToken, idenPoolId, userPool) {
let region = idenPoolId.split(":")[0];
let provider = "cognito-idp." + region + ".amazonaws.com/" + userPool;
let login = {};
login[provider] = idToken;
console.log(provider + ' || ' + idenPoolId);
// Add the User's Id Token to the Cognito credentials login map.
let credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: idenPoolId,
Logins: login
});
//call refresh method in order to authenticate user and get new temp credentials
credentials.get((error) => {
if (error) {
console.error(error);
} else {
console.log('Successfully logged!');
console.log('AKI:'+ credentials.accessKeyId);
console.log('AKS:'+ credentials.secretAccessKey);
console.log('token:' + credentials.sessionToken);
}
});
}
秘密密钥access key,
令牌`访问您的API。它会根据您在步骤2中配置的经过身份验证的角色而具有权限。
对于未经身份验证的访问,显然会跳过登录步骤,但是您仍然可以生成用于访问API的临时密钥。示例代码非常相似,只有一个关键区别。不需要and
参数。
Logins
这组密钥的权限取决于您在步骤2中所设置的未经身份验证的角色。
function getUnauthToken(idenPoolId) {
console.log(idenPoolId);
// Add the User's Id Token to the Cognito credentials login map.
let credentials = new AWS.CognitoIdentityCredentials({
IdentityPoolId: idenPoolId,
});
credentials.get((error) => {
if (error) {
console.error(error);
} else {
console.log('Unauth AKI:'+ credentials.accessKeyId);
console.log('Unauth AKS:'+ credentials.secretAccessKey);
console.log('Unauth token:' + credentials.sessionToken);
}
});
}
-这是我的API网关创建角色的方式及其政策。 CFN yaml中的示例
Roles
因此,根据以上角色,我对身份验证和未身份验证的用户具有不同的访问权限。唯一需要注意的是,您的AuthenticatedRole:
Type: "AWS::IAM::Role"
Properties:
RoleName: "AuthenticatedRole"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: "Allow"
Action:
- "sts:AssumeRoleWithWebIdentity"
Principal:
Federated:
- "cognito-identity.amazonaws.com"
Condition:
StringEquals:
cognito-identity.amazonaws.com:aud: <your identity pool id>
ForAnyValue:StringLike:
cognito-identity.amazonaws.com:amr: authenticated
Path: "/"
AuthRolePolicy:
Type: "AWS::IAM::Policy"
Properties:
PolicyName: AuthRolePolicy
PolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: "Allow"
Action: "execute-api:Invoke"
Resource:
- "arn:aws:execute-api:<region>:<account id>:<api id>/*/*/acc/*"]]
Roles:
-
Ref: AuthenticatedRole
UnauthRole:
Type: "AWS::IAM::Role"
Properties:
RoleName: UnauthRole
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: "Allow"
Action:
- "sts:AssumeRoleWithWebIdentity"
Principal:
Federated:
- "cognito-identity.amazonaws.com"
Condition:
StringEquals:
cognito-identity.amazonaws.com:aud: <your identity pool id>
Path: "/"
UnauthRolePolicy:
Type: "AWS::IAM::Policy"
Properties:
PolicyName: UnauthRolePolicy
PolicyDocument:
Version: "2012-10-17"
Statement:
-
Effect: "Allow"
Action: "execute-api:Invoke"
Resource:
- "arn:aws:execute-api:<region>:<account id>:<api id>/*/GET"/acc/dept/12/*"]]
Roles:
-
Ref: UnauthRole
必须是秘密的(即在浏览器中公开不是一件好事)。
希望这会有所帮助。