身份验证与安全¶
访问 Admin API GraphQL 端点¶
访问 Admin API GraphQL 端点,需要您的服务器生成有效的 JWT,并将其作为 Authorization HTTP 头包含在请求中。
临时访问令牌¶
可以从 高级 -> Admin API 页面获取临时访问令牌,用于快速测试。该访问令牌的有效期为 5 分钟。
获取用于签名 JWT 的私钥¶
- 进入 高级 -> Admin API
- 点击 下载 以下载私钥,并将其提供给您的服务器使用。
- 复制 密钥 ID,并将其提供给您的服务器使用。
使用私钥生成 JWT¶
生成 JWT 的示例代码¶
以下是使用私钥生成 JWT 的示例代码。
package main
import (
"encoding/json"
"fmt"
"os"
"time"
"github.com/lestrrat-go/jwx/v3/jwa"
"github.com/lestrrat-go/jwx/v3/jwk"
"github.com/lestrrat-go/jwx/v3/jws"
"github.com/lestrrat-go/jwx/v3/jwt"
)
// Replace "myapp" with your project ID here.
// It is the first part of your Authgear endpoint.
// e.g. The project ID is "myapp" for "https://myapp.authanyid.com"
const ProjectID = "myapp"
// Replace "mykid" with the key ID you see in the portal.
const KeyID = "mykid"
func main() {
// Replace the following call with your own way to get the private key.
f, err := os.Open("private-key.pem")
if err != nil {
panic(err)
}
defer f.Close()
jwkSet, err := jwk.ParseReader(f, jwk.WithPEM(true))
if err != nil {
panic(err)
}
key, _ := jwkSet.Key(0)
key.Set("kid", KeyID)
now := time.Now().UTC()
payload := jwt.New()
_ = payload.Set(jwt.AudienceKey, ProjectID)
_ = payload.Set(jwt.IssuedAtKey, now.Unix())
_ = payload.Set(jwt.ExpirationKey, now.Add(5*time.Minute).Unix())
// The alg MUST be RS256.
alg := jwa.RS256()
hdr := jws.NewHeaders()
hdr.Set("typ", "JWT")
buf, err := json.Marshal(payload)
if err != nil {
panic(err)
}
token, err := jws.Sign(buf, jws.WithKey(alg, key, jws.WithProtectedHeaders(hdr)))
if err != nil {
panic(err)
}
fmt.Printf("%v\n", string(token))
}
import jwt
from datetime import datetime, timedelta
private_key = open("private-key.pem", "r").read()
# Replace "myapp" with your project ID here.
# It is the first part of your Authgear endpoint.
# e.g. The project ID is "myapp" for "https://myapp.authanyid.com"
PROJECT_ID = "myapp"
# Replace "mykid" with the key ID you see in the portal.
KEY_ID = "mykid"
now = datetime.now()
payload = {
"aud": [PROJECT_ID],
"iat": int(now.timestamp()),
"exp": int((now + timedelta(minutes=5)).timestamp()),
}
token = jwt.encode(
payload,
private_key,
"RS256",
headers={
"kid": KEY_ID,
},
)
print(token)
本示例使用 Express.js 和 JsonWebToken 包。请先使用以下命令安装这两个包:
以及
以下是用于生成 JWT 的 Express.js 应用代码:
const express = require("express");
const node_jwt = require('jsonwebtoken');
const fs = require('fs');
const app = express();
const port = 3002;
app.get('/', (request, response) => {
// Your project ID is the first part of your Authgear endpoint.
// e.g. The project ID is "myapp" for "https://myapp.authanyid.com"
// You can find your key ID in the Portal.
const project_id = ""; //Place your Authgear project id
const key_id = ""; // Place your Authgear key ID
const expiresAt = Math.floor(Date.now() / 1000) + (60 * 5); //the current value means token will expire in 5 minutes.
//Payload to include in JWT
const claims = {
aud: project_id,
iat: Math.floor(Date.now() / 1000),
exp: expiresAt
}
const privateKey = fs.readFileSync("key.pem"); //Read value from the downloaded key file
const header = {"typ": "JWT", "kid": key_id, "alg": "RS256"}
const jwt = node_jwt.sign(claims, privateKey, { header: header });
response.send("Generated JWT: " + jwt);
});
app.listen(port, () => {
console.log("server started on port " + port);
});
以下示例是一个基础的 Spring Boot 应用。
首先,在依赖块中添加以下内容以安装 JJWT 包:
dependencies {
implementation 'io.jsonwebtoken:jjwt-api:0.12.6'
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.12.6'
runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.12.6'
}
然后,按如下方式编写您的 Java 代码:
import java.io.InputStream;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Base64;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.core.io.ClassPathResource;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import io.jsonwebtoken.Jwts;
@SpringBootApplication
@RestController
public class DemoApplication {
private static PrivateKey privateKey;
static {
try {
// Load the private key from the PEM file (assuming it's in the classpath)
ClassPathResource resource = new ClassPathResource("key.pem"); // store your downloaded Admin API key.pem in
// the resources folder.
InputStream inputStream = resource.getInputStream();
byte[] keyBytes = FileCopyUtils.copyToByteArray(inputStream);
String privateKeyPEM = new String(keyBytes, "UTF-8");
// Clean PEM string (remove header, footer, and newlines)
privateKeyPEM = privateKeyPEM
.replace("-----BEGIN PRIVATE KEY-----", "")
.replace("-----END PRIVATE KEY-----", "")
.replaceAll("\\n", "");
// Decode the PEM string to get the raw key bytes
byte[] decodedKey = Base64.getDecoder().decode(privateKeyPEM);
// Generate the private key object from the bytes
KeyFactory keyFactory = KeyFactory.getInstance("RSA"); // Use RSA
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decodedKey);
privateKey = keyFactory.generatePrivate(keySpec);
} catch (Exception e) {
// Handle the exception appropriately (e.g., log, throw a more specific
// exception)
System.err.println("Error loading or parsing private key: " + e.getMessage());
throw new RuntimeException("Failed to initialize private key", e);
}
}
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@GetMapping("/generateJwt")
public String generateJwt() {
String kid = ""; // The key ID for your Admin API Key. Can be found in
// Authgear Portal under Advanced > Admin API.
String projectId = ""; // Your Authgear project ID. You can find this in Authgear Portal.
int expirationInMinutes = 15; // how long the JWT will be valid for.
Date now = new Date();
Date expiration = new Date(now.getTime() + 30 * expirationInMinutes * 1000);
Map<String, Object> claims = new HashMap<>();
claims.put("aud", projectId);
claims.put("iat", now);
claims.put("exp", expiration);
String jwt = Jwts.builder()
.header()
.add("kid", kid)
.and()
.claims(claims)
.signWith(privateKey, Jwts.SIG.RS256)
.compact();
return "{\"jwt\": \"" + jwt + "\"}";
}
}
以下示例展示了一个 ASP.NET Core API。
首先,安装所需的依赖:
接下来,为您项目的 ID、kid、私钥文件(.pem 文件)路径以及 JWT 的有效期创建以下字段变量。
private const string ProjectId = ""; // Replace with actual project ID
private const string KeyId = ""; // Replace with key ID from the portal
private const int ExpiryMinutes = 5;
private const string PrivateKeyPath = "key.pem"; // Path to PEM file
然后,实现一个 GetPrivateKey 方法,用于从您的 .pem 文件中获取私钥。
private RSA GetPrivateKey(string privateKeyPem)
{
var rsa = RSA.Create();
rsa.ImportFromPem(privateKeyPem.ToCharArray());
return rsa;
}
实现一个 GenerateJwt 方法。该方法会使用私钥和 kid 生成 JWT。
private string GenerateJwt(RSA privateKey)
{
DateTime now = DateTime.UtcNow;
var securityKey = new RsaSecurityKey(privateKey)
{
KeyId = KeyId // Set the Key ID
};
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.RsaSha256);
var descriptor = new SecurityTokenDescriptor
{
Audience = ProjectId,
IssuedAt = now,
Expires = now.AddMinutes(ExpiryMinutes),
SigningCredentials = credentials
};
var tokenHandler = new JwtSecurityTokenHandler();
var token = tokenHandler.CreateToken(descriptor);
return tokenHandler.WriteToken(token);
}
最后,在您的路由方法中读取 .pem 文件并获取私钥,然后调用 GenerateJwt() 方法生成 JWT。
[HttpGet(Name = "Jwt")]
public IActionResult GenerateJwt()
{
try
{
// Read private key from file
string privateKeyPem = System.IO.File.ReadAllText(PrivateKeyPath);
RSA privateKey = GetPrivateKey(privateKeyPem);
// Generate JWT
string token = GenerateJwt(privateKey);
return Ok(new { token });
}
catch (Exception ex)
{
return BadRequest(new { message = $"Error generating JWT: {ex.Message}" });
}
}
首先,使用以下命令安装 Firebase PHP JWT 包:
用于生成 JWT 的 PHP 代码:
<?php
require 'vendor/autoload.php';
use Firebase\JWT\JWT;
// Your project ID is the first part of your Authgear endpoint.
// e.g. The project ID is "myapp" for "https://myapp.authanyid.com"
// You can find your key ID in the Portal.
$project_id = ""; // Place your Authgear project id
$key_id = ""; // Place your Authgear key ID
$expiresAt = time() + (60*5); //the current value means token will expire in 5 minutes.
//Payload to include in JWT
$claims = [
"aud" => $project_id,
"iat" => time(),
"exp" => $expiresAt
];
$privateKey = file_get_contents("./key.pem"); //Read value from the downloaded key file
$header = [
"typ" => "JWT",
"kid" => $key_id,
"alg" => "RS256"
];
$jwt = JWT::encode($claims, $privateKey, "RS256", null, $header);
echo $jwt;
JWT 头示例¶
JWT 负载示例¶
在 HTTP 请求中包含 JWT¶
生成 JWT 后,您必须在发送给 Admin API 端点的每一个请求中都包含它。示例如下
该请求头是标准的 Authorization HTTP 头。令牌类型必须为 Bearer。
可选:缓存 JWT¶
正如示例代码中所示,JWT 的有效期为 5 分钟。您可以延长其有效期并进行缓存,以避免每次请求都重新生成。
轮换 Admin API 密钥¶
您应定期更换用于验证 API 请求的 API 密钥。这样可以将密钥泄露带来的影响降到最低,从而提升安全性。
要轮换 API 密钥
- 进入 管理台 > 高级 > Admin API
- 在「Admin API 密钥列表」下,点击「生成新密钥对」
- 此时,两个密钥都可以用于验证 Admin API 请求。
- 确保您所有的系统都已更新为使用新密钥
- 删除旧的 API 密钥