API参考

本文档提供 user.blym.top OAuth 2.0服务的完整API参考。

基础信息

项目
基础URL https://user.blym.top
授权端点 /oauth/authorize.php
令牌端点 /oauth/token.php
用户信息端点 /api/userinfo.php
令牌验证端点 /api/tokeninfo.php

授权端点

端点信息

项目
URL /oauth/authorize.php
方法 GET
内容类型 text/html

请求参数

参数 类型 必填 说明
client_id string 客户端ID
redirect_uri string 回调地址
response_type string 固定值 code
scope string 请求的作用域
state string 推荐 CSRF防护状态值
code_challenge string PKCE挑战码
code_challenge_method string PKCE方法:S256/plain
nonce string OpenID Connect nonce

请求示例

GET /oauth/authorize.php?client_id=client_abc123&redirect_uri=https%3A%2F%2Fexample.com%2Fcallback&response_type=code&scope=openid%20profile%20email&state=xyz789

成功响应

重定向到回调地址:

HTTP/1.1 302 Found
Location: https://example.com/callback?code=a1b2c3d4e5f6&state=xyz789

错误响应

重定向到回调地址并附带错误参数:

HTTP/1.1 302 Found
Location: https://example.com/callback?error=access_denied&error_description=The+user+denied+the+authorization+request&state=xyz789

错误代码

错误代码 说明
invalid_request 请求缺少必要参数
unauthorized_client 客户端未授权
access_denied 用户拒绝授权
unsupported_response_type 不支持的response_type
invalid_scope 请求的作用域无效
server_error 服务器内部错误

令牌端点

端点信息

项目
URL /oauth/token.php
方法 POST
内容类型 application/x-www-form-urlencoded 或 application/json

授权码模式

请求参数

参数 类型 必填 说明
grant_type string 固定值 authorization_code
code string 授权码
redirect_uri string 回调地址
client_id string 客户端ID
client_secret string 是* 客户端密钥
code_verifier string PKCE验证码

*公开客户端(使用PKCE)可不提供client_secret

请求示例

POST /oauth/token.php HTTP/1.1
Host: user.blym.top
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code&code=a1b2c3d4e5f6&redirect_uri=https%3A%2F%2Fexample.com%2Fcallback&client_id=client_abc123&client_secret=secret_xyz789

成功响应

HTTP/1.1 200 OK
Content-Type: application/json

{
    "access_token": "at_a1b2c3d4e5f6g7h8i9j0",
    "token_type": "Bearer",
    "expires_in": 3600,
    "refresh_token": "rt_k1l2m3n4o5p6q7r8s9t0",
    "scope": "openid profile email",
    "id_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}

刷新令牌模式

请求参数

参数 类型 必填 说明
grant_type string 固定值 refresh_token
refresh_token string 刷新令牌
client_id string 客户端ID
client_secret string 客户端密钥
scope string 新的作用域(可缩小)

请求示例

POST /oauth/token.php HTTP/1.1
Host: user.blym.top
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token&refresh_token=rt_k1l2m3n4o5p6q7r8s9t0&client_id=client_abc123&client_secret=secret_xyz789

成功响应

{
    "access_token": "at_new_token_here",
    "token_type": "Bearer",
    "expires_in": 3600,
    "refresh_token": "rt_new_refresh_token",
    "scope": "openid profile email"
}

客户端凭证模式

请求参数

参数 类型 必填 说明
grant_type string 固定值 client_credentials
client_id string 客户端ID
client_secret string 客户端密钥
scope string 请求的作用域

请求示例

POST /oauth/token.php HTTP/1.1
Host: user.blym.top
Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials&client_id=client_abc123&client_secret=secret_xyz789&scope=read

错误响应

HTTP/1.1 400 Bad Request
Content-Type: application/json

{
    "error": "invalid_grant",
    "error_description": "Authorization code has expired"
}

错误代码

错误代码 HTTP状态码 说明
invalid_request 400 请求缺少必要参数
invalid_client 401 客户端认证失败
invalid_grant 400 授权码/刷新令牌无效
unauthorized_client 400 客户端未授权
unsupported_grant_type 400 不支持的授权类型
invalid_scope 400 请求的作用域无效

用户信息端点

端点信息

项目
URL /api/userinfo.php
方法 GET
认证 Bearer Token

请求头

Authorization: Bearer {access_token}

请求示例

GET /api/userinfo.php HTTP/1.1
Host: user.blym.top
Authorization: Bearer at_a1b2c3d4e5f6g7h8i9j0

成功响应

HTTP/1.1 200 OK
Content-Type: application/json

{
    "sub": "123",
    "name": "张三",
    "preferred_username": "zhangsan",
    "email": "zhangsan@example.com",
    "email_verified": true,
    "client_id": "client_abc123",
    "scope": "openid profile email"
}

响应字段说明

字段 类型 说明 条件
sub string 用户唯一标识 始终返回
name string 用户显示名称 profile作用域
preferred_username string 用户名 profile作用域
email string 用户邮箱 email作用域
email_verified boolean 邮箱是否验证 email作用域
client_id string 客户端ID 始终返回
scope string 授予的作用域 始终返回

错误响应

HTTP/1.1 401 Unauthorized
Content-Type: application/json
WWW-Authenticate: Bearer error="invalid_token", error_description="Invalid or expired access token"

{
    "error": "invalid_token",
    "error_description": "Invalid or expired access token"
}

令牌验证端点

端点信息

项目
URL /api/tokeninfo.php
方法 GET
认证 Bearer Token

请求示例

GET /api/tokeninfo.php HTTP/1.1
Host: user.blym.top
Authorization: Bearer at_a1b2c3d4e5f6g7h8i9j0

成功响应

HTTP/1.1 200 OK
Content-Type: application/json

{
    "active": true,
    "client_id": "client_abc123",
    "user_id": "123",
    "scope": "openid profile email",
    "exp": 1234567890,
    "iat": 1234563290,
    "token_type": "Bearer",
    "username": "zhangsan",
    "email": "zhangsan@example.com"
}

无效令牌响应

HTTP/1.1 200 OK
Content-Type: application/json

{
    "active": false
}

作用域说明

作用域 说明 用户信息端点返回
openid OpenID Connect基本身份 sub
profile 用户基本资料 name, preferred_username
email 用户邮箱 email, email_verified
read 读取用户数据 根据API定义
write 写入用户数据 根据API定义
admin 管理员权限 根据API定义

速率限制

端点 限制
/oauth/token.php 100次/分钟/IP
/api/userinfo.php 1000次/小时/令牌

超过限制将返回:

HTTP/1.1 429 Too Many Requests

{
    "error": "too_many_requests",
    "error_description": "Rate limit exceeded"
}

SDK示例

PHP

<?php
class OAuthClient {
    private $clientId;
    private $clientSecret;
    private $redirectUri;
    private $baseUrl = 'https://user.blym.top';
    
    public function __construct($clientId, $clientSecret, $redirectUri) {
        $this->clientId = $clientId;
        $this->clientSecret = $clientSecret;
        $this->redirectUri = $redirectUri;
    }
    
    public function getAuthorizationUrl($state, $scope = 'openid profile email') {
        $params = http_build_query([
            'client_id' => $this->clientId,
            'redirect_uri' => $this->redirectUri,
            'response_type' => 'code',
            'scope' => $scope,
            'state' => $state
        ]);
        return $this->baseUrl . '/oauth/authorize.php?' . $params;
    }
    
    public function getAccessToken($code) {
        $ch = curl_init($this->baseUrl . '/oauth/token.php');
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
            'grant_type' => 'authorization_code',
            'code' => $code,
            'redirect_uri' => $this->redirectUri,
            'client_id' => $this->clientId,
            'client_secret' => $this->clientSecret
        ]));
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        $response = curl_exec($ch);
        curl_close($ch);
        return json_decode($response, true);
    }
    
    public function getUserInfo($accessToken) {
        $ch = curl_init($this->baseUrl . '/api/userinfo.php');
        curl_setopt($ch, CURLOPT_HTTPHEADER, [
            'Authorization: Bearer ' . $accessToken
        ]);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        $response = curl_exec($ch);
        curl_close($ch);
        return json_decode($response, true);
    }
}

// 使用示例
$client = new OAuthClient(
    'your_client_id',
    'your_client_secret',
    'https://your-app.com/callback'
);

// 生成授权URL
$authUrl = $client->getAuthorizationUrl(uniqid());

// 获取令牌
$tokens = $client->getAccessToken($_GET['code']);

// 获取用户信息
$userInfo = $client->getUserInfo($tokens['access_token']);
?>

JavaScript

class OAuthClient {
    constructor(clientId, clientSecret, redirectUri) {
        this.clientId = clientId;
        this.clientSecret = clientSecret;
        this.redirectUri = redirectUri;
        this.baseUrl = 'https://user.blym.top';
    }
    
    getAuthorizationUrl(state, scope = 'openid profile email') {
        const params = new URLSearchParams({
            client_id: this.clientId,
            redirect_uri: this.redirectUri,
            response_type: 'code',
            scope: scope,
            state: state
        });
        return `${this.baseUrl}/oauth/authorize.php?${params}`;
    }
    
    async getAccessToken(code) {
        const response = await fetch(`${this.baseUrl}/oauth/token.php`, {
            method: 'POST',
            headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
            body: new URLSearchParams({
                grant_type: 'authorization_code',
                code: code,
                redirect_uri: this.redirectUri,
                client_id: this.clientId,
                client_secret: this.clientSecret
            })
        });
        return response.json();
    }
    
    async getUserInfo(accessToken) {
        const response = await fetch(`${this.baseUrl}/api/userinfo.php`, {
            headers: { 'Authorization': `Bearer ${accessToken}` }
        });
        return response.json();
    }
}