配置

这是 GraphQL 库版本 7 的文档。对于长期支持 (LTS) 版本 5,请参考 GraphQL 库版本 5 LTS

Neo4j GraphQL 库使用 JSON Web Token (JWT) 认证。JWT 是包含关于发起请求的用户或客户端的声明或语句的令牌。这些声明可以包括用户 ID 或角色等信息。

JWT 可以从认证服务获取,然后包含在 API 请求中。如果 JWT 有效,API 会验证 JWT 并返回请求的数据。

实例化

Neo4j GraphQL 库可以接受两种类型的 JWT

  • 请求上下文的 token 字段中的编码 JWT。

  • 请求上下文的 jwt 字段中的已解码 JWT。

编码 JWT

为了使用编码 JWT,请配置库以使用密钥解码和验证令牌。以下代码块使用 Apollo Server。它从请求中提取 Authorization 标头并将其放入相应的上下文字段中

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 有效负载放入上下文的 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,请使用上下文的 token 字段。使用 Apollo Server 时,将授权标头提取到上下文的 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

或者,您可以在上下文中传入一个 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 类似的方式传递到上下文。但是,它不是使用 token,而是使用 jwt 字段

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

定义

"""
Instructs @neo4j/graphql that the flagged object represents the relevant JWT payload
"""
directive @jwt on OBJECT

用法

如果配置一个附加的 roles 声明(它是位于 JWT 有效负载根目录的字符串数组),请将以下内容添加到类型定义中

type JWT @jwt {
    roles: [String!]!
}

类型名称 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")
}

path 必须转义两次:一次用于 GraphQL,一次用于 dot-prop,后者在底层用于解析路径。

© . All rights reserved.