JWT 配置
|
这是 GraphQL Library 7 版本的文档。对于长期支持 (LTS) 版本 5,请参考 GraphQL Library 5 LTS 版本。 |
Neo4j GraphQL 库使用 JSON Web Token(JWT)认证。JWT 是包含关于发起请求的用户或客户端的声明或陈述的令牌。这些声明可以包括用户的 ID 或角色等信息。
可以从身份验证服务获取 JWT,然后将其包含在 API 请求中。API 会验证 JWT,如果 JWT 有效,则返回请求的数据。
实例化
Neo4j GraphQL 库可以接受两种类型的 JWT
-
已编码的 JWT 位于请求上下文的
token字段中。 -
已解码的 JWT 位于请求上下文的
jwt字段中。
已编码的 JWT
要使用已编码的 JWT,需要使用密钥对库进行配置,以解码并验证令牌。以下代码块使用 Apollo Server。它从请求中提取 Authorization 头并将其放入相应的 context 字段。
const server = new ApolloServer({
schema, // schema from Neo4jGraphQL.getSchema()
});
const { url } = await startStandaloneServer(server, {
listen: { port: 4000 },
context: async ({ req }) => ({
token: req.headers.authorization,
}),
});
如果需要自定义解码机制,也可以对同一头进行解码,并将得到的 JWT 负载放入 context 的 jwt 字段。
另外,您可以通过 JWKS 端点 解码令牌。
对称密钥
要使用对称密钥(例如 “secret”)配置库,需要进行如下实例化:
new Neo4jGraphQL({
typeDefs,
features: {
authorization: {
key: "secret",
},
},
});
JWKS 端点
要配置库以通过 JSON Web Key Set(JWKS)端点(例如 “https://www.example.com/.well-known/jwks.json”)验证令牌,需要进行如下实例化:
new Neo4jGraphQL({
typeDefs,
features: {
authorization: {
key: {
url: "https://www.myapplication.com/.well-known/jwks.json"
},
},
},
});
传入已编码的 JWT
要传入已编码的 JWT,请使用 context 的 token 字段。在使用 Apollo Server 时,将 Authorization 头提取到 context 的 token 属性中。
const server = new ApolloServer({
schema,
});
await startStandaloneServer(server, {
context: async ({ req }) => ({ token: req.headers.authorization }),
});
例如,带有以下 authorization 头的 HTTP 请求应如下所示:
POST / HTTP/1.1
authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJyb2xlcyI6WyJ1c2VyX2FkbWluIiwicG9zdF9hZG1pbiIsImdyb3VwX2FkbWluIl19.IY0LWqgHcjEtOsOw60mqKazhuRFKroSXFQkpCtWpgQI
content-type: application/json
另外,您可以向 context 传入类型为 JwtPayload 的键 jwt,其定义如下:
// standard claims https://datatracker.ietf.org/doc/html/rfc7519#section-4.1
interface JwtPayload {
[key: string]: any;
iss?: string | undefined;
sub?: string | undefined;
aud?: string | string[] | undefined;
exp?: number | undefined;
nbf?: number | undefined;
iat?: number | undefined;
jti?: string | undefined;
}
|
请勿传入头部或签名。 |
已解码的 JWT
已解码的 JWT 以类似于已编码 JWT 的方式传入 context。不过,它使用 jwt 字段而不是 token。
const jwt = customImplementation();
const { url } = await startStandaloneServer(server, {
listen: { port: 4000 },
context: async ({ req }) => ({
jwt: jwt,
}),
});
customImplementation 是提供已解码 JWT 的函数占位符。在 context 中使用 jwt 而不是 token 可告知 Neo4j GraphQL 库无需对其进行解码。
添加 JWT 声明
默认情况下,JWT 规范中 已注册的声明名称 支持过滤。
可以使用 @jwt 指令以及在某些情况下使用 @jwtClaim 指令,为额外的 JWT 声明配置过滤。
@jwt
@jwtClaim
定义
"""
Instructs @neo4j/graphql that the flagged field has a mapped path within the JWT Payload.
"""
directive @jwtClaim(
"""
The path of the field in the real JWT as mapped within the JWT Payload.
"""
path: String!
) on FIELD_DEFINITION
用法
roles 声明不一定位于 JWT 负载根部,它也可以位于嵌套位置,例如在 myApplication 下。
{
"sub": "user1234",
"myApplication": {
"roles": ["user", "admin"]
}
}
在这种情况下,请同时使用 @jwtClaim 指令和 @jwt 指令。
type JWT @jwt {
roles: [String!]! @jwtClaim(path: "myApplication.roles")
}
此外,嵌套位置的路径中可能包含 . 字符,例如:
{
"sub": "user1234",
"http://www.myapplication.com": {
"roles": ["user", "admin"]
}
}
这些字符必须进行转义。
type JWT @jwt {
roles: [String!]! @jwtClaim(path: "http://www\\\\.myapplication\\\\.com.roles")
}
|
|