Appsync Resolver 没有电子邮件声明
Appsync Resolver no email in claim
我创建了一个使用电子邮件地址的解析器 ($context.identity.claims.email)。我在 AWS 控制台 "Queries" 部分测试了我的查询,一切正常,因为 $context.identity.claims 看起来符合预期;
{
sub: 'xxx-xxx-xxx-xxx-xxx',
aud: 'xxxxxxxxx',
email_verified: true,
sub: 'xxx-xxx-xxx-xxx-xxx',
token_use: 'id',
auth_time: 1563643503,
iss: 'https://cognito-idp.ap-southeast-1.amazonaws.com/ap-southeast-1_xxxxx',
'cognito:username': 'xxxx',
exp: 1563647103,
iat: 1563643503,
email: 'xxx@xxx.xxx'
}
一切看起来都不错,所以让我们在我的 React 应用程序中使用它,该应用程序使用 AWS Amplify 代码进行身份验证。它现在不起作用,那是因为索赔部分没有 "email"!看起来像这样;
{
sub: 'xxx-xxx-xxx-xxx-xxx',
event_id: 'xxx-xxx-xxx-xxx-xxx',
token_use: 'access',
scope: 'aws.cognito.signin.user.admin',
auth_time: 1563643209,
iss: 'https://cognito-idp.ap-southeast-1.amazonaws.com/ap-southeast-1_xxxx',
exp: 1563646809,
iat: 1563643209,
jti: 'xxx-xxx-xxx-xxx-xxx',
client_id: 'xxxx',
username: 'xxxx'
}
谁能帮我解决为什么电子邮件显示在 AWS 控制台查询中,但当我从自己的客户端调用它时却没有?
猜测在您的 React 应用程序中,您正在检索用户属性,其效果为
import { Auth } from 'aws-amplify';
async componentDidMount() {
const currentUser = await Auth.currentUserInfo();
const claims = currentUser.attributes;
// verification logic here, and here you cannot find claims['email']
}
要检查的一件事是特定的 React App 客户端是否可以访问 'email' 属性。客户端可能不允许使用特定属性。
在 AWS Cognito 控制台 > 用户池 > 常规设置 > 应用程序客户端中,您应该会看到类似下面屏幕截图的内容。
找到特定的应用程序客户端(匹配 Id)。单击 'Set attribute read and write permissions' - 红色下划线。在那里,您应该能够 select 电子邮件属性为该客户端可读。
好的,所以我认为它们在 "token_use" 元素中。我的原始代码使用了这个功能;
import {API, graphqlOperation} from 'aws-amplify';
import * as queries from '../../graphql/queries';
async function makeCall() {
let resp = await API.graphql(graphqlOperation(queries.getMeta));
return resp.data.getMeta;
}
该代码产生了上面观察到的结果。如果我使用以下(非常脏但有效)代码,我会得到上述预期结果;
import {Auth, API, graphqlOperation} from 'aws-amplify';
import axios from 'axios';
import * as queries from '../../graphql/queries';
async function makeCall() {
const curSesh = await Auth.currentSession();
const token = curSesh.idToken.jwtToken;
const resp = await axios({
method: 'post',
url: API._options.aws_appsync_graphqlEndpoint,
data: graphqlOperation(queries.getMeta),
headers: {
authorization: token
}
});
return resp.data.data.getMeta;
}
我不会将此标记为已解决,因为我确信有一种更简洁的方法可以使它正常工作。如果有人能阐明它,我很乐意学习。
我有一个关于 Amplify 功能的请求,我得到了以下出色的解决方案建议
TLDR:更新您的 Auth Provider 以创建 "pre-token generation" Lambad,并在您的 lambda 中添加另一个 'fake' 组到声明中,因为这些组是传递给 AppSync[ 的令牌的一部分=11=]
有关此 repo 中解决方案的更多详细信息
Amplify 可以配置为通过传入函数为每个 graphql 请求包含当前 ID 令牌。两个配置选项如下所示:
import { Auth } from 'aws-amplify';
const getIdToken = async () => ({
Authorization: (await Auth.currentSession()).getIdToken().getJwtToken()
});
const aws_exports = {
aws_appsync_graphqlEndpoint: 'https://****.appsync-api.us-east-2.amazonaws.com/graphql',
aws_appsync_region: 'us-east-2',
aws_appsync_authenticationType: 'AMAZON_COGNITO_USER_POOLS',
// OPTION 1
graphql_headers: getIdToken,
// OPTION 2
// API: {
// graphql_headers: getIdToken
// },
Auth: {
identityPoolId: 'us-east-2:********-****-****-****-************',
region: 'us-east-2',
userPoolId: 'us-east-2_*********',
userPoolWebClientId: '*************************',
type: 'AMAZON_COGNITO_USER_POOLS'
}
};
export default aws_exports;
Amplify.configure(awsconfig);
请注意解析器在访问和 ID 令牌之间可用的不同声明。
访问令牌将提供 client_id
、jti
和 scope
等声明,而 ID 令牌声明将提供 email
、phone_number
等。 ,以及 aud
、cognito:roles
和 cognito:username
.
等其他人
访问令牌
{
"claims": {
"auth_time": 1581438574,
"client_id": "*************************",
"cognito:groups": [
"Admin"
],
"event_id": "ec70594c-b02b-4015-ad0b-3c207a18a362",
"exp": 1581442175,
"iat": 1581438575,
"iss": "https://cognito-idp.us-east-2.amazonaws.com/us-east-2_*********",
"jti": "351d2d5f-13c3-4de8-ba7c-b3c5a9e46ca6",
"scope": "aws.cognito.signin.user.admin",
"sub": "********-****-****-****-************",
"token_use": "access",
"username": "********-****-****-****-************"
},
...
}
ID 令牌
{
"claims": {
"address": {
"formatted": "1984 Newspeak Dr"
},
"aud": "....",
"auth_time": 1581438671,
"birthdate": "1984-04-04",
"cognito:groups": [
"Admin"
],
"cognito:roles": [
"arn:aws:iam::012345678901:role/us-east-2-ConsumerRole"
],
"cognito:username": "********-****-****-****-************",
"email": "winston.smith@oceania.gov",
"email_verified": true,
"event_id": "e3087488-bfc8-4d08-a44c-089c4ae7d8ec",
"exp": 1581442271,
"gender": "Male",
"iat": 1581438672,
"iss": "https://cognito-idp.us-east-2.amazonaws.com/us-east-2_*********",
"name": "WINSTON SMITH",
"phone_number": "+15551111984",
"phone_number_verified": false,
"sub": "********-****-****-****-************",
"token_use": "id"
},
...
}
测试 amplify-js@2.2.4
来源:https://github.com/aws-amplify/amplify-js/blob/aws-amplify%402.2.4/packages/api/src/API.ts#L86-L107
我创建了一个使用电子邮件地址的解析器 ($context.identity.claims.email)。我在 AWS 控制台 "Queries" 部分测试了我的查询,一切正常,因为 $context.identity.claims 看起来符合预期;
{
sub: 'xxx-xxx-xxx-xxx-xxx',
aud: 'xxxxxxxxx',
email_verified: true,
sub: 'xxx-xxx-xxx-xxx-xxx',
token_use: 'id',
auth_time: 1563643503,
iss: 'https://cognito-idp.ap-southeast-1.amazonaws.com/ap-southeast-1_xxxxx',
'cognito:username': 'xxxx',
exp: 1563647103,
iat: 1563643503,
email: 'xxx@xxx.xxx'
}
一切看起来都不错,所以让我们在我的 React 应用程序中使用它,该应用程序使用 AWS Amplify 代码进行身份验证。它现在不起作用,那是因为索赔部分没有 "email"!看起来像这样;
{
sub: 'xxx-xxx-xxx-xxx-xxx',
event_id: 'xxx-xxx-xxx-xxx-xxx',
token_use: 'access',
scope: 'aws.cognito.signin.user.admin',
auth_time: 1563643209,
iss: 'https://cognito-idp.ap-southeast-1.amazonaws.com/ap-southeast-1_xxxx',
exp: 1563646809,
iat: 1563643209,
jti: 'xxx-xxx-xxx-xxx-xxx',
client_id: 'xxxx',
username: 'xxxx'
}
谁能帮我解决为什么电子邮件显示在 AWS 控制台查询中,但当我从自己的客户端调用它时却没有?
猜测在您的 React 应用程序中,您正在检索用户属性,其效果为
import { Auth } from 'aws-amplify';
async componentDidMount() {
const currentUser = await Auth.currentUserInfo();
const claims = currentUser.attributes;
// verification logic here, and here you cannot find claims['email']
}
要检查的一件事是特定的 React App 客户端是否可以访问 'email' 属性。客户端可能不允许使用特定属性。
在 AWS Cognito 控制台 > 用户池 > 常规设置 > 应用程序客户端中,您应该会看到类似下面屏幕截图的内容。
找到特定的应用程序客户端(匹配 Id)。单击 'Set attribute read and write permissions' - 红色下划线。在那里,您应该能够 select 电子邮件属性为该客户端可读。
好的,所以我认为它们在 "token_use" 元素中。我的原始代码使用了这个功能;
import {API, graphqlOperation} from 'aws-amplify';
import * as queries from '../../graphql/queries';
async function makeCall() {
let resp = await API.graphql(graphqlOperation(queries.getMeta));
return resp.data.getMeta;
}
该代码产生了上面观察到的结果。如果我使用以下(非常脏但有效)代码,我会得到上述预期结果;
import {Auth, API, graphqlOperation} from 'aws-amplify';
import axios from 'axios';
import * as queries from '../../graphql/queries';
async function makeCall() {
const curSesh = await Auth.currentSession();
const token = curSesh.idToken.jwtToken;
const resp = await axios({
method: 'post',
url: API._options.aws_appsync_graphqlEndpoint,
data: graphqlOperation(queries.getMeta),
headers: {
authorization: token
}
});
return resp.data.data.getMeta;
}
我不会将此标记为已解决,因为我确信有一种更简洁的方法可以使它正常工作。如果有人能阐明它,我很乐意学习。
我有一个关于 Amplify 功能的请求,我得到了以下出色的解决方案建议
TLDR:更新您的 Auth Provider 以创建 "pre-token generation" Lambad,并在您的 lambda 中添加另一个 'fake' 组到声明中,因为这些组是传递给 AppSync[ 的令牌的一部分=11=]
有关此 repo 中解决方案的更多详细信息
Amplify 可以配置为通过传入函数为每个 graphql 请求包含当前 ID 令牌。两个配置选项如下所示:
import { Auth } from 'aws-amplify';
const getIdToken = async () => ({
Authorization: (await Auth.currentSession()).getIdToken().getJwtToken()
});
const aws_exports = {
aws_appsync_graphqlEndpoint: 'https://****.appsync-api.us-east-2.amazonaws.com/graphql',
aws_appsync_region: 'us-east-2',
aws_appsync_authenticationType: 'AMAZON_COGNITO_USER_POOLS',
// OPTION 1
graphql_headers: getIdToken,
// OPTION 2
// API: {
// graphql_headers: getIdToken
// },
Auth: {
identityPoolId: 'us-east-2:********-****-****-****-************',
region: 'us-east-2',
userPoolId: 'us-east-2_*********',
userPoolWebClientId: '*************************',
type: 'AMAZON_COGNITO_USER_POOLS'
}
};
export default aws_exports;
Amplify.configure(awsconfig);
请注意解析器在访问和 ID 令牌之间可用的不同声明。
访问令牌将提供 client_id
、jti
和 scope
等声明,而 ID 令牌声明将提供 email
、phone_number
等。 ,以及 aud
、cognito:roles
和 cognito:username
.
访问令牌
{
"claims": {
"auth_time": 1581438574,
"client_id": "*************************",
"cognito:groups": [
"Admin"
],
"event_id": "ec70594c-b02b-4015-ad0b-3c207a18a362",
"exp": 1581442175,
"iat": 1581438575,
"iss": "https://cognito-idp.us-east-2.amazonaws.com/us-east-2_*********",
"jti": "351d2d5f-13c3-4de8-ba7c-b3c5a9e46ca6",
"scope": "aws.cognito.signin.user.admin",
"sub": "********-****-****-****-************",
"token_use": "access",
"username": "********-****-****-****-************"
},
...
}
ID 令牌
{
"claims": {
"address": {
"formatted": "1984 Newspeak Dr"
},
"aud": "....",
"auth_time": 1581438671,
"birthdate": "1984-04-04",
"cognito:groups": [
"Admin"
],
"cognito:roles": [
"arn:aws:iam::012345678901:role/us-east-2-ConsumerRole"
],
"cognito:username": "********-****-****-****-************",
"email": "winston.smith@oceania.gov",
"email_verified": true,
"event_id": "e3087488-bfc8-4d08-a44c-089c4ae7d8ec",
"exp": 1581442271,
"gender": "Male",
"iat": 1581438672,
"iss": "https://cognito-idp.us-east-2.amazonaws.com/us-east-2_*********",
"name": "WINSTON SMITH",
"phone_number": "+15551111984",
"phone_number_verified": false,
"sub": "********-****-****-****-************",
"token_use": "id"
},
...
}
测试 amplify-js@2.2.4
来源:https://github.com/aws-amplify/amplify-js/blob/aws-amplify%402.2.4/packages/api/src/API.ts#L86-L107