Genyleap/Docs
OpenProof / 开发

通过标准 OAuth/OIDC 连接任何应用。

OpenProof 在协议边界上与编程语言无关。适合时使用随附 SDK;也可以从任何支持 HTTPS 与 OAuth 2.0/OpenID Connect 的语言完成集成。

集成模型

流程Authorization Code + PKCE
Your app
   ↓ redirect
OpenProof /oauth/authorize
   ↓
authentication / provider / passkey / wallet
   ↓
your callback?code=...&state=...&iss=...
   ↓ code + verifier
OpenProof /oauth/token
   ↓
access_token + id_token + optional refresh_token

产品集成应使用 OAuth/OIDC token。安全的 OpenProof session cookie 属于 OpenProof 的 account/admin origin,不应复制到你的产品 domain。

从 Discovery 开始

URL替换 auth.example.com
https://auth.example.com/.well-known/openid-configuration
https://auth.example.com/.well-known/jwks.json

对于可复用 client,Discovery 是获取 authorization、token、UserInfo、introspection 以及其他相关协议 endpoint 的首选方式。

注册你的产品

具有 IAL2 的活跃 owner 可以使用 /admin/console 或 administration API。

创建 application

curl需要 owner session
curl --fail-with-body -b owner.cookies \
  https://auth.example.com/admin/applications \
  -H 'Content-Type: application/json' \
  -d '{
    "identifier":"example-web",
    "name":"Example Web",
    "environment":"production"
  }'

创建 client

curlweb client
curl --fail-with-body -b owner.cookies \
  https://auth.example.com/admin/clients \
  -H 'Content-Type: application/json' \
  -d '{
    "application_id":"APPLICATION_ID",
    "name":"Example Web",
    "kind":"web",
    "redirect_uris":["https://app.example.com/oauth/callback"],
    "scopes":["openid","profile","offline_access"]
  }'
类型常见 clientSecret
browserSPA / 仅浏览器
nativeiOS / Android / desktop
webServer-rendered / backend Web 应用仅返回一次;仅限 backend
serviceMachine-to-machine仅返回一次

Authorization Code + PKCE S256

生成随机 verifier,推导其 S256 challenge,并生成随机 state and nonce.。verifier/state/nonce 仅应在该次登录事务的生命周期内保存。

authorization 请求概念示例
GET /oauth/authorize?
  response_type=code
  &client_id=CLIENT_ID
  &redirect_uri=https://app.example.com/oauth/callback
  &scope=openid profile offline_access
  &code_challenge=PKCE_CHALLENGE
  &code_challenge_method=S256
  &state=STATE
  &nonce=NONCE

在 callback 中,要求返回的 state and iss 在 token exchange 前与事务/已配置 issuer 一致。

Token 交换

curlapplication/x-www-form-urlencoded
curl --fail-with-body https://auth.example.com/oauth/token \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode 'grant_type=authorization_code' \
  --data-urlencode 'client_id=CLIENT_ID' \
  --data-urlencode 'code=AUTHORIZATION_CODE' \
  --data-urlencode 'redirect_uri=https://app.example.com/oauth/callback' \
  --data-urlencode 'code_verifier=PKCE_VERIFIER'

ID token 验证

使用 issuer JWKS 验证 RS256 签名。至少验证 iss, aud, exp, iat 以及原始 nonce;同时还应处理 nbf, azp and at_hash (如存在)。

JavaScript / 浏览器

repository 提供了一个面向浏览器的 SDK package,名为 @openproof/identity.。它会生成 PKCE/state/nonce,验证 callback 的 state/issuer,并使用 JWKS 验证 RS256 ID token。

javascriptpublic browser client
import { OpenProofIdentity } from "@openproof/identity";

const identity = new OpenProofIdentity({
  issuer: "https://auth.example.com",
  clientId: "CLIENT_ID",
  redirectUri: "https://app.example.com/oauth/callback",
  scopes: ["openid", "profile", "offline_access"]
});

await identity.login();
javascriptcallback
const tokens = await identity.handleCallback();

console.log(tokens.id_token_claims.sub);

const profile =
  await identity.userInfo(tokens.access_token);
浏览器 client 没有 client secret。

绝不要嵌入机密的 web or service client secret 放入交付给用户的 JavaScript 中。

Node.js

为你的 framework 使用成熟的 OIDC client,或对已文档化协议使用原生 fetch() 。机密 credential 应保存在服务器环境/secret store 中。

javascriptserver-side token exchange
const body = new URLSearchParams({
  grant_type: "authorization_code",
  client_id: process.env.OPENPROOF_CLIENT_ID,
  code,
  redirect_uri: "https://app.example.com/oauth/callback",
  code_verifier: verifier
});

const response = await fetch(
  "https://auth.example.com/oauth/token",
  {
    method: "POST",
    headers: {
      "content-type":
        "application/x-www-form-urlencoded"
    },
    body
  }
);

if (!response.ok) {
  throw new Error(
    `OpenProof token exchange failed: ${response.status}`
  );
}

const tokens = await response.json();

请使用 OIDC/JWT library 处理 JWKS caching、签名验证与 claim validation,而不是自行实现密码学验证。

PHP

任何仍在维护的 PHP OAuth/OIDC library 都可以将 OpenProof 作为 issuer。直接协议就是标准 HTTPS 与 form-encoded OAuth。

phptoken exchange
<?php

$payload = http_build_query([
    'grant_type' => 'authorization_code',
    'client_id' => getenv('OPENPROOF_CLIENT_ID'),
    'code' => $_GET['code'],
    'redirect_uri' =>
        'https://app.example.com/oauth/callback',
    'code_verifier' =>
        $_SESSION['openproof_pkce_verifier'],
]);

$curl = curl_init(
    'https://auth.example.com/oauth/token'
);

curl_setopt_array($curl, [
    CURLOPT_POST => true,
    CURLOPT_POSTFIELDS => $payload,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Content-Type: application/x-www-form-urlencoded'
    ],
]);

$body = curl_exec($curl);

if ($body === false) {
    throw new RuntimeException(curl_error($curl));
}

使用维护良好的 JWT/OIDC package 与 issuer JWKS 验证 ID token。不要临时自行实现 RSA/JWK 验证。

C++

repository 中的 C++26 SDK 导出为 openproof.sdk.。它与 transport 无关,因此可以继续使用现有的 Boost.Beast、Qt Network 或 libcurl stack。

c++SDK 配置
import openproof.sdk;

auto config =
    openproof::sdk::ClientConfig::create(
        "https://auth.example.com",
        "CLIENT_ID",
        "http://127.0.0.1:49152/callback",
        {"openid", "profile", "offline_access"});

openproof::sdk::IdentityClient client{
    std::move(config).value()
};

auto login = client.beginLogin();

std::cout <<
    login->authorizationUrl()
    << '\n';

SDK 提供登录事务创建、authorization-code request 构建、refresh 与 UserInfo helper。最小 relying-party 示例位于 examples/reference-client.

Python、Go、Rust、Java、C# 及其他语言

无需使用 OpenProof 专用 SDK。将符合标准的 OAuth/OIDC library 配置为使用 OpenProof issuer。最小安全实现流程为:Discovery → PKCE/state/nonce → authorization redirect → callback checks → token exchange → JWKS signature/claim validation → access-token authorization。

UserInfo 与 refresh

curlUserInfo
curl --fail-with-body \
  https://auth.example.com/oauth/userinfo \
  -H 'Authorization: Bearer ACCESS_TOKEN'
curlrefresh token
curl --fail-with-body \
  https://auth.example.com/oauth/token \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode 'grant_type=refresh_token' \
  --data-urlencode 'client_id=CLIENT_ID' \
  --data-urlencode 'refresh_token=REFRESH_TOKEN'

Refresh token 会轮换。以原子方式持久化新 token 并丢弃旧值。Replay protection 可能会撤销整个 token family。

保护你的 API

使用精确 audience 与最小化 scope 注册 resource。

curl注册 resource
curl --fail-with-body -b owner.cookies \
  https://auth.example.com/admin/resources \
  -H 'Content-Type: application/json' \
  -d '{
    "audience":"https://api.example.com/rides",
    "name":"Ride API",
    "scopes":["rides:read","rides:request"]
  }'

backend 应检查 token 有效性、精确 audience、所需 scope 与产品业务规则。token 有效本身并不足以构成完整 authorization。

Introspection

curl机密 backend
curl --fail-with-body \
  https://auth.example.com/oauth/introspect \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode 'client_id=CONFIDENTIAL_CLIENT_ID' \
  --data-urlencode 'client_secret=CLIENT_SECRET' \
  --data-urlencode 'token=ACCESS_TOKEN'

OpenProof gateway

另一种方式是将产品 route 放在 OpenProof 后方,并在 proxy 到 backend 之前通过静态 route policy 强制 role、assurance、scope 与 audience。

Service 间

使用 service client,配置允许的 audience/scope,然后通过以下方式请求 access token: client_credentials.

curlmachine grant
curl --fail-with-body \
  https://auth.example.com/oauth/token \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode 'grant_type=client_credentials' \
  --data-urlencode 'client_id=CLIENT_ID' \
  --data-urlencode 'client_secret=CLIENT_SECRET' \
  --data-urlencode 'scope=rides:dispatch' \
  --data-urlencode 'resource=https://api.example.com/dispatch'

结果仅包含 access token,不包含 refresh token 或用户 session。

Account API

启用 account self-service 与 verification delivery 后,OpenProof 会提供注册、已验证邮箱/电话所有权、密码重置、profile、TOTP、recovery code 与 passkey。

用途Endpoint
注册POST /account/signup
邮箱验证POST /account/email/verify
开始重置密码POST /account/password/forgot
完成密码重置POST /account/password/reset
资料GET/PATCH /account/profile
TOTP 注册POST /account/totp/start/complete
Passkey 登录POST /auth/passkey/options/verify
已关联方式GET /account/connections
一个 canonical identity。

不要使用 Google/GitHub 邮箱作为产品用户的 key。用户可以关联多种登录方式,同时保持同一个稳定的 OpenProof subject。

错误处理与 secret 管理

错误包含稳定 code、对 client 安全的消息与 request ID。逻辑应基于 code/status,而不是文本。401 视为认证缺失/无效,403 视为 authority/assurance 不足,409 视为 state conflict,429 视为 backoff signal。

绝不要记录 password、TOTP/recovery code、verification secret、authorization code、access/refresh token、机密 client secret、cookie、DPoP proof 或 private key。