{ "version": "https://jsonfeed.org/version/1", "title": "OAuth", "description": "", "home_page_url": "go/oauth", "feed_url": "feed/oauth.json", "items": [ { "author": { "url": "member/Authing", "name": "Authing", "avatar": "https://cdn.v2ex.com/avatar/b759/896b/570457_large.png?m=1683190646" }, "url": "t/937303", "title": "\u6388\u6743\u7801 + PKCE \u6a21\u5f0f\uff5c OIDC & OAuth2.0 \u8ba4\u8bc1\u534f\u8bae\u6700\u4f73\u5b9e\u8df5\u7cfb\u5217 [03]", "id": "t/937303", "date_published": "2023-05-04T09:10:45+00:00", "content_html": "

\"\u56fe\u7247\"\n\u5728\u4e0a\u4e00\u7bc7\u6587\u7ae0\u4e2d\uff0c\u6211\u4eec\u4ecb\u7ecd\u4e86\u00a0OIDC\u00a0\u6388\u6743\u7801\u6a21\u5f0f\uff0c\u672c\u6b21\u6211\u4eec\u5c06\u91cd\u70b9\u56f4\u7ed5 \u6388\u6743\u7801 + PKCE \u6a21\u5f0f\uff08 Authorization Code With PKCE \uff09\u8fdb\u884c\u4ecb\u7ecd \uff0c\u4ece\u800c\u8ba9\u4f60\u7684\u7cfb\u7edf\u5feb\u901f\u5177\u5907\u63a5\u5165\u7528\u6237\u8ba4\u8bc1\u7684\u6807\u51c6\u4f53\u7cfb\u3002OIDC & OAuth2.0 \u8ba4\u8bc1\u534f\u8bae\u6700\u4f73\u5b9e\u8df5\u7cfb\u5217 02 - \u6388\u6743\u7801\u6a21\u5f0f\uff08 Authorization Code \uff09\u63a5\u5165 Authing\n\"\u56fe\u7247\"

\n

\u4e3a\u4ec0\u4e48\u4f1a\u6709 PKCE \u6a21\u5f0f\uff1a

\n

PKCE\u00a0\u662f Proof Key for Code Exchange \u7684\u7f29\u5199\uff0cPKCE \u662f\u4e00\u79cd\u7528\u4e8e\u589e\u5f3a\u6388\u6743\u7801\u6a21\u5f0f\u5b89\u5168\u6027\u7684\u65b9\u6cd5\uff0c\u5b83\u53ef\u4ee5\u9632\u6b62\u6076\u610f\u5e94\u7528\u7a0b\u5e8f\u901a\u8fc7\u622a\u83b7\u6388\u6743\u7801\u548c\u91cd\u5b9a\u5411 URI \u6765\u83b7\u5f97\u8bbf\u95ee\u4ee4\u724c\u3002PKCE \u901a\u8fc7\u5c06\u968f\u673a\u5b57\u7b26\u4e32\uff08 code_verifier \uff09\u548c\u5176 SHA-256 \u54c8\u5e0c\u503c\uff08 code_challenge \uff09\u4e0e\u6388\u6743\u8bf7\u6c42\u4e00\u8d77\u53d1\u9001\uff0c\u786e\u4fdd\u8bbf\u95ee\u4ee4\u724c\u53ea\u80fd\u7531\u5177\u6709\u76f8\u5e94 code_verifier \u7684\u5e94\u7528\u7a0b\u5e8f\u4f7f\u7528\uff0c\u4fdd\u969c\u7528\u6237\u7684\u5b89\u5168\u6027\u3002

\n

[ OAuth 2.0 \u534f\u8bae\u6269\u5c55] PKCE \u6269\u5c55\u534f\u8bae\uff1a\u4e3a\u4e86\u89e3\u51b3\u516c\u5f00\u5ba2\u6237\u7aef\u7684\u6388\u6743\u5b89\u5168\u95ee\u9898

\n

\u300c\u9762\u5411\u5bf9\u8c61\u300d public \u5ba2\u6237\u7aef\uff0c\u5176\u672c\u8eab\u6ca1\u6709\u80fd\u529b\u4fdd\u5b58\u5bc6\u94a5\u4fe1\u606f\uff08\u6076\u610f\u653b\u51fb\u8005\u53ef\u4ee5\u901a\u8fc7\u53cd\u7f16\u8bd1\u7b49\u624b\u6bb5\u67e5\u770b\u5230\u5ba2\u6237\u7aef\u7684\u5bc6\u94a5 client_secret \uff0c \u4e5f\u5c31\u53ef\u4ee5\u901a\u8fc7\u6388\u6743\u7801 code \u6362\u53d6 access_token \uff0c \u5230\u8fd9\u4e00\u6b65\uff0c\u6076\u610f\u5e94\u7528\u5c31\u53ef\u4ee5\u62ff\u7740 token \u8bf7\u6c42\u8d44\u6e90\u670d\u52a1\u5668\u4e86\uff09

\n

\u300c\u539f\u7406\u300d PKCE \u534f\u8bae\u672c\u8eab\u662f\u5bf9\u00a0OAuth 2.0\u00a0\u7684\u6269\u5c55\uff0c \u5b83\u548c\u4e4b\u524d\u7684\u6388\u6743\u7801\u6d41\u7a0b\u5927\u4f53\u4e0a\u662f\u4e00\u81f4\u7684\uff0c \u533a\u522b\u5728\u4e8e\u5728\u5411\u6388\u6743\u670d\u52a1\u5668\u7684 authorize endpoint \u8bf7\u6c42\u65f6\uff0c\u9700\u8981\u989d\u5916\u7684 code_challenge \u548c code_challenge_method \u53c2\u6570\uff1b\u5411 token endpoint \u8bf7\u6c42\u65f6\uff0c \u9700\u8981\u989d\u5916\u7684 code_verifier \u53c2\u6570\u3002\u6700\u540e\u6388\u6743\u670d\u52a1\u5668\u4f1a\u5bf9\u8fd9\u4e09\u4e2a\u53c2\u6570\u8fdb\u884c\u5bf9\u6bd4\u9a8c\u8bc1\uff0c \u901a\u8fc7\u540e\u9881\u53d1\u4ee4\u724c\u3002

\n

01.\u6388\u6743\u7801 + PKCE \u6a21\u5f0f\uff08 Authorization Code With PKCE \uff09

\n

\u5982\u679c\u4f60\u7684\u5e94\u7528\u662f\u4e00\u4e2a SPA \u524d\u7aef\u5e94\u7528\u6216\u79fb\u52a8\u7aef App \uff0c\u5efa\u8bae\u4f7f\u7528\u6388\u6743\u7801 + PKCE \u6a21\u5f0f\u6765\u5b8c\u6210\u7528\u6237\u7684\u8ba4\u8bc1\u548c\u6388\u6743\u3002\u6388\u6743\u7801 + PKCE \u6a21\u5f0f\u9002\u5408\u4e0d\u80fd\u5b89\u5168\u5b58\u50a8\u5bc6\u94a5\u7684\u573a\u666f\uff08\u4f8b\u5982\u524d\u7aef\u6d4f\u89c8\u5668)

\n

\u6211\u4eec\u89e3\u91ca\u4e0b code_verifier \u548c code_challenge\n\u5bf9\u4e8e\u6bcf\u4e00\u4e2a OAuth/OIDC \u8bf7\u6c42\uff0c\u5ba2\u6237\u7aef\u4f1a\u5148\u521b\u5efa\u4e00\u4e2a\u4ee3\u7801\u9a8c\u8bc1\u5668 code_verifier

\n

code_verifier\uff1a\u5728 [A-Z] / [a-z] / [0-9] / \"-\" / \".\" / \"_\" / \"~\" \u8303\u56f4\u5185\uff0c\u751f\u6210 43-128 \u4f4d\u7684\u968f\u673a\u5b57\u7b26\u4e32\u3002

\n

code_challenge\uff1a\u5219\u662f\u5bf9 code_verifier \u901a\u8fc7 code_challenge_method \u4f8b\u5982 sha256 \u8f6c\u6362\u5f97\u6765\u7684\u3002

\n

\u7528\u5927\u767d\u8bdd\u8bb2\u4e0b\u5c31\u662f\u5728\u8ba4\u8bc1\u662f\u7528\u6237\u643a\u5e26\u7684\u662f\u52a0\u5bc6\u540e\u7684 code_challenge \uff0c\u5728\u7528\u6237\u8ba4\u8bc1\u6210\u529f\u901a\u8fc7 code \u83b7\u53d6 Token \u65f6\uff0c\u5ba2\u6237\u7aef\u8bc1\u660e\u81ea\u5df1\u7684\u65b9\u5f0f\u5219\u662f\u628a code_verifier \u539f\u6587\u53d1\u9001\uff0c\u8ba4\u8bc1\u4e2d\u5fc3\u6536\u5230\u83b7\u53d6 Token \u8bf7\u6c42\u65f6\u901a\u8fc7 code_verifier + code_challenge_method \u8fdb\u884c\u8f6c\u6362\uff0c\u53d1\u73b0\u6700\u7ec8\u7ed3\u679c\u4e0e code_challenge \u5339\u914d\u5219\u8fd4\u56de Token \uff0c\u5426\u5219\u62d2\u7edd\u3002

\n

1.1 \u6574\u4f53\u6d41\u7a0b

\n

\u6574\u4f53\u4e0a\uff0c\u6709\u4ee5\u4e0b\u6d41\u7a0b:

\n

1.\u7528\u6237\u70b9\u51fb\u767b\u5f55\u3002\n2.\u5728\u4f60\u7684\u5e94\u7528\u4e2d\uff0c\u751f\u6210 code_verifier \u548c code_challenge \u3002\n3.\u62fc\u63a5\u767b\u5f55\u94fe\u63a5(\u5305\u542b code_challenge ) \u8df3\u8f6c\u5230 Authing \u8bf7\u6c42\u8ba4\u8bc1\u3002\n4.Authing \u53d1\u73b0\u7528\u6237\u6ca1\u6709\u767b\u5f55\uff0c\u91cd\u5b9a\u5411\u5230\u8ba4\u8bc1\u9875\u9762\uff0c\u8981\u6c42\u7528\u6237\u5b8c\u6210\u8ba4\u8bc1\u3002\n5.\u7528\u6237\u5728\u6d4f\u89c8\u5668\u5b8c\u6210\u8ba4\u8bc1\u3002\n6.Authing \u670d\u52a1\u5668\u901a\u8fc7\u6d4f\u89c8\u5668\u901a\u8fc7\u91cd\u5b9a\u5411\u5c06\u6388\u6743\u7801\uff08 code \uff09\u53d1\u9001\u5230\u4f60\u7684\u5e94\u7528\u524d\u7aef\u3002\n7.\u4f60\u7684\u5e94\u7528\u5c06\u6388\u6743\u7801 (code) \u548c code_verifier \u53d1\u9001\u5230 Authing \u8bf7\u6c42\u83b7\u53d6 Token.\n8.Authing \u6821\u9a8c code \u3001code_verifier \u548c code_challenge \u3002\n9.\u6821\u9a8c\u901a\u8fc7\uff0cAuthing \u5219\u8fd4\u56de AccessToken \u548c IdToken \u4ee5\u53ca\u53ef\u9009\u7684 RefreshToken \u3002\n10.\u4f60\u7684\u5e94\u7528\u73b0\u5728\u77e5\u9053\u4e86\u7528\u6237\u7684\u8eab\u4efd\uff0c\u540e\u7eed\u4f7f\u7528 AccessToken \u6362\u53d6\u7528\u6237\u4fe1\u606f\uff0c\u8c03\u7528\u8d44\u6e90\u65b9\u7684 API \u7b49

\n

\"\u56fe\u7247\"

\n

1.2 \u51c6\u5907\u63a5\u5165

\n

1.2.1 \u6574\u4f53\u6d41\u7a0b

\n

\u9700\u8981\u5148\u5728 Authing \u521b\u5efa\u5e94\u7528\uff1a\n\"\u56fe\u7247\"\n\u914d\u7f6e\u767b\u5f55\u56de\u8c03\u548c\u767b\u51fa\u56de\u8c03\uff0c\u914d\u7f6e\u4e3a\u4f60\u5b9e\u9645\u9879\u76ee\u7684\u5730\u5740\uff0c\u6211\u4eec\u5728\u8fd9\u91cc\u914d\u7f6e localhost \u7528\u4e8e\u6d4b\u8bd5\u3002\n\u82e5\u4f60\u60f3\u5339\u914d\u591a\u4e2a\u767b\u5f55 /\u767b\u51fa\u56de\u8c03\n\u53ef\u4ee5\u4f7f\u7528 \u2018*\u2019 \u53f7\u8fdb\u884c\u901a\u914d\uff0c\u767b\u5f55 /\u767b\u51fa\u56de\u8c03\u53ef\u4ee5\u662f\u5982\u4e0b\u683c\u5f0f\n\"\u56fe\u7247\"

\n

\"\u56fe\u7247\"\n\u5728\u534f\u8bae\u914d\u7f6e\u4e2d\uff0c\u6211\u4eec\u52fe\u9009 authorization_code \u5e76\u4e14\u4f7f\u7528 code \u4f5c\u4e3a\u8fd4\u56de\u7c7b\u578b\uff0c\u5982\u4e0b\u56fe\u6240\u793a\uff1aPKCE \u6a21\u5f0f\u4f7f\u7528\u7684\u662f code_verifier \u6765\u6362\u53d6 Token \uff0c\u6240\u4ee5\u9700\u8981\u914d\u7f6e\u83b7\u53d6 Token \u7684\u65b9\u5f0f\u4e3a null\n\"\u56fe\u7247\"

\n

1.3 \u63a5\u5165\u6d4b\u8bd5

\n

1.3.1 \u6240\u9700\u8c03\u7528\u63a5\u53e3\u5217\u8868

\n
GET${host}/oidc/auth \u53d1\u8d77\u767b\u5f55\uff08\u62fc\u63a5\u4f60\u7684\u53d1\u8d77\u767b\u5f55\u5730\u5740\uff09\nPOST${host}/oidc/token \u83b7\u53d6 \nTokenGET${host}/oidc/me \u83b7\u53d6\u7528\u6237\u4fe1\u606f\nPOST${host}/oidc/token/introspection \u6821\u9a8c \nTokenPOST${host}/oidc/token \u5237\u65b0 \nTokenPOST${host}/oidc/revocation \u540a\u9500 \nTokenGET${host}/session/end \u767b\u51fa\n
\n

1.3.2 Run in Postman \u6240\u9700\u8c03\u7528\u63a5\u53e3\u5217\u8868

\n

https://app.getpostman.com/run-collection/24730905-5d29e488-719e-4ffe-af21-a7c18298d328?action=collection%2Ffork&collection-url=entityId%3D24730905-5d29e488-719e-4ffe-af21-a7c18298d328%26entityType%3Dcollection%26workspaceId%3D13ff793c-024c-459d-b1f6-87e91c4769ed#env%5BAuthing%20OIDC%5D=W3sia2V5IjoiaG9zdCIsInZhbHVlIjoiaHR0cHM6Ly9kZWVwbGFuZy5hdXRoaW5nLmNuIiwiZW5hYmxlZCI6dHJ1ZSwidHlwZSI6ImRlZmF1bHQifSx7ImtleSI6ImNsaWVudF9pZCIsInZhbHVlIjoiNjM4MmNmNDg2ZTVhNjk0NDNhZjI5NzFiIiwiZW5hYmxlZCI6dHJ1ZSwidHlwZSI6ImRlZmF1bHQifSx7ImtleSI6ImNsaWVudF9zZWNyZXQiLCJ2YWx1ZSI6Ijc3NWMyM2NlMjkwYzkwZDQwNDUxNGU3MDgyMDkzZWIzIiwiZW5hYmxlZCI6dHJ1ZSwidHlwZSI6ImRlZmF1bHQifSx7ImtleSI6ImFjY2Vzc190b2tlbiIsInZhbHVlIjoiIiwiZW5hYmxlZCI6dHJ1ZSwidHlwZSI6ImRlZmF1bHQifSx7ImtleSI6ImlkX3Rva2VuIiwidmFsdWUiOiIiLCJlbmFibGVkIjp0cnVlLCJ0eXBlIjoiZGVmYXVsdCJ9LHsia2V5IjoicmVmcmVzaF90b2tlbiIsInZhbHVlIjoiIiwiZW5hYmxlZCI6dHJ1ZSwidHlwZSI6ImRlZmF1bHQifV0=

\n

1.3.3 \u53d1\u8d77\u767b\u5f55

\n

GET${host}/oidc/auth

\n

\u8fd9\u662f\u57fa\u4e8e\u6d4f\u89c8\u5668\u7684 OIDC \u7684\u8d77\u70b9\uff0c\u8bf7\u6c42\u5bf9\u7528\u6237\u8fdb\u884c\u8eab\u4efd\u9a8c\u8bc1\uff0c\u5e76\u4f1a\u5728\u9a8c\u8bc1\u6210\u529f\u540e\u8fd4\u56de\u6388\u6743\u7801\u5230\u60a8\u6240\u6307\u5b9a\u7684 redirect_uri \u3002

\n

\u751f\u6210 code_challenge \u548c code_verifier

\n

\u5728\u7ebf\u751f\u6210\nhttps://tonyxu-io.github.io/pkce-generator/

\n

\u79bb\u7ebf\u751f\u6210\n\u9996\u5148\uff0c\u6211\u4eec\u8981\u751f\u6210\u4e00\u4e2a code_challenge \u548c code_verifier,\u4ee5\u4e0b\u662f\u4f7f\u7528 Javascript \u8bed\u8a00\u751f\u6210 PKCE \u6240\u9700\u8981\u7684 code_verifier \u548c code_challenge \u7684\u811a\u672c\uff1a

\n
// \u751f\u6210\u968f\u673a\u5b57\u7b26\u4e32\nfunction generateRandomString(length) {\n var result = '';\n var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';\n var charactersLength = characters.length;\n for (var i = 0; i < length; i++) {\n result += characters.charAt(Math.floor(Math.random() * charactersLength));\n }\n return result;\n}\n// \u751f\u6210 code_verifier\nvar codeVerifier = generateRandomString(128);\n// \u5bf9 code_verifier \u8fdb\u884c SHA-256 \u7f16\u7801\uff0c\u5e76\u5c06\u5176\u8f6c\u6362\u4e3a base64url \u683c\u5f0f\u7684 code_challenge\nvar sha256 = new jsSHA(\"SHA-256\", \"TEXT\");\nsha256.update(codeVerifier);\nvar codeChallenge = btoa(String.fromCharCode.apply(null, new Uint8Array(sha256.getHash(\"ARRAYBUFFER\"))))\n .replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n// \u5c06 code_verifier \u548c code_challenge \u7528\u5bf9\u8c61\u5f62\u5f0f\u8fd4\u56de\nvar pkce = {\n codeVerifier: codeVerifier,\n codeChallenge: codeChallenge\n};\n\n
\n

\u4ee5\u4e0a\u4ee3\u7801\u4f7f\u7528 jsSHA \u5e93\u8ba1\u7b97 SHA-256 \u54c8\u5e0c\u503c\uff0c\u4f7f\u7528 base64url \u7f16\u7801\u5c06\u54c8\u5e0c\u503c\u8f6c\u6362\u4e3a code_challenge \u3002\u4f60\u53ef\u4ee5\u5c06\u4ee5\u4e0a\u4ee3\u7801\u590d\u5236\u5230\u4f60\u7684 Javascript \u4ee3\u7801\u4e2d\uff0c\u5e76\u4f7f\u7528 pkce.codeVerifier \u548c pkce.codeChallenge \u8c03\u7528 OAuth 2.0 \u6388\u6743\u8bf7\u6c42\u3002

\n

\u4e3e\u4f8b

\n
code_verifier:4aHg5fN1AGdbnBAfVKMf9ZMK4PUOBTwQSKKk9V8wYXOFYDZklMl7dzDUhnQi4sYhzGb6PWCkNQqLP70K1DNOneEDq8iyASepAdGjGBBmCs4BGCDDJNwLrGpnJEfmrI66\n
\n

code_verifier \u7684\u957f\u5ea6\u4e3a 43 \uff5e 128 \uff0c\u6211\u4eec\u751f\u6210\u7684\u662f 128 \u4f4d

\n
code_challenge:OhMk95M9qWkKd06--utVtRzQh8Y0Qtqo4cPqqzMJyMw\n
\n

\u53d1\u8d77\u767b\u5f55\u5730\u5740\uff08\u6d4f\u89c8\u5668\u4e2d\u6253\u5f00\uff09\nhttps://{host}/oidc/auth?scope=openid+profile+offline_access+username+email+phone&redirect_uri=http://localhost:8080/&response_type=code&prompt=consent&nOnce=6e187def-1a19-4067-8875-653f024d5a9f&client_id={client_id}&state=1676881862&code_challenge={code_challenge}&code_challenge_method=S256

\n

\u4f53\u9a8c\u5730\u5740\nhttps://oidc-authorizationcode-withpkce.authing.cn/oidc/auth?scope=openid+profile+offline_access+username+email+phone&redirect_uri=http://localhost:8080/&response_type=code&prompt=consent&nOnce=6e187def-1a19-4067-8875-653f024d5a9f&client_id=63f30f5bf629268cc27d93c6&state=1676881862&code_challenge=OhMk95M9qWkKd06--utVtRzQh8Y0Qtqo4cPqqzMJyMw&code_challenge_method=S256

\n

\u53c2\u6570\u8bf4\u660e\n\"\u56fe\u7247\"

\n

1.3.4 \u83b7\u53d6 Token

\n

POST${host}/oidc/token\n\u7528\u6237\u5728 Authing \u4fa7\u5b8c\u6210\u767b\u5f55\u64cd\u4f5c\u540e\uff0cAuthing \u4f1a\u5c06\u751f\u6210\u7684 code \u4f5c\u4e3a\u53c2\u6570\u56de\u8c03\u5230 redirect_uri \u5730\u5740\uff0c\u6b64\u65f6\u901a\u8fc7 code \u6362 token \u63a5\u53e3\u5373\u53ef\u62ff\u5230\u5bf9\u5e94\u7684\u8bbf\u95ee\u4ee4\u724c access_token

\n

\u8bf7\u6c42\u53c2\u6570\n\"\u56fe\u7247\"\n\u8bf7\u6c42\u793a\u4f8b

\n
curl --location --request POST 'https://{host}/oidc/token' \\\n--header 'Content-Type: application/x-www-form-urlencoded' \\\n--data-urlencode 'client_id={\u5e94\u7528 ID}' \\\n--data-urlencode 'client_secret={\u5e94\u7528\u5bc6\u94a5}' \\\n--data-urlencode 'grant_type=authorization_code' \\\n--data-urlencode 'redirect_uri={\u53d1\u8d77\u767b\u5f55\u65f6\u6307\u5b9a\u7684 redirect_uri}' \\\n--data-urlencode 'code={/oidc/auth \u8fd4\u56de\u7684 code}' \\\n--data-urlencode 'code_verifier={code_verifier}' \n\n
\n

\u54cd\u5e94\u793a\u4f8b\uff08\u6210\u529f\uff09

\n
{\n\"scope\": \"openid username email phone offline_access profile\",\n\"token_type\": \"Bearer\",\n\"access_token\": \"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6ImVtSzBGbVRIa0xlQWFjeS1YWEpVT3J6SzkxV243TkdoNGFlYUVlSjVQOUUifQ.eyJzdWIiOiI2M2ViNTNjNDQxYTVjMmYwNWYyNGJiMDMiLCJhdWQiOiI2M2ViNDU4NTE1NmQ5NzcxMDFkZDM3NTAiLCJzY29wZSI6Im9wZW5pZCB1c2VybmFtZSBlbWFpbCBwaG9uZSBvZmZsaW5lX2FjY2VzcyBwcm9maWxlIiwiaWF0IjoxNjc2MzY2OTE0LCJleHAiOjE2Nzc1NzY1MTQsImp0aSI6ImVmVU04enNrbl92LXYzeXZfbDVHRV9fQ2JEY0NNZDhEVDFnYVI0bHRqcHAiLCJpc3MiOiJodHRwczovL29pZGMtYXV0aG9yaXphdGlvbi1jb2RlLmF1dGhpbmcuY24vb2lkYyJ9.E3gAYzCQbJmrtM5zl91OPHm2YPnDxzRejw75oVMF1tLqCS0trj6CSBxyxP3Z9t6Eb_oAu1f_3I6XC3KC-l0DTM6q7_R2rnW4LWlik2rDCLuGpG0FqFScLZhwafmrPsVn93yaBQfEEoaLviqKhj3DgOymKqHZzFG3taaz2k_pWsxt4z97DtKjRTiqyMvcSfHsVrjSKELaC-5S_PHPWcQ70iX85IwUb6i5ldZGxYmODCvChNC9p4D4IOT3atvyEHgBTmjA9ZKI-T7hCVHSO91WZY3l1p4iWdi6KdP1oMGTy8WbmUHG9SiWO1Efh_9I5ZpRzVNWXINLv-lZ0d2aZKjg2w\",\n\"expires_in\": 1209600,\n\"id_token\": \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiI2M2ViNTNjNDQxYTVjMmYwNWYyNGJiMDMiLCJhdWQiOiI2M2ViNDU4NTE1NmQ5NzcxMDFkZDM3NTAiLCJpYXQiOjE2NzYzNjY5MTQsImV4cCI6MTY3NzU3NjUxNCwiaXNzIjoiaHR0cHM6Ly9vaWRjLWF1dGhvcml6YXRpb24tY29kZS5hdXRoaW5nLmNuL29pZGMiLCJub25jZSI6IjhiYjg3MjdhLWU1MGUtNDUzOC05ZmZmLWZhOTFlNWQ0Y2MwYSIsIm5hbWUiOm51bGwsImdpdmVuX25hbWUiOm51bGwsIm1pZGRsZV9uYW1lIjpudWxsLCJmYW1pbHlfbmFtZSI6bnVsbCwibmlja25hbWUiOm51bGwsInByZWZlcnJlZF91c2VybmFtZSI6bnVsbCwicHJvZmlsZSI6bnVsbCwicGljdHVyZSI6Imh0dHBzOi8vZmlsZXMuYXV0aGluZy5jby9hdXRoaW5nLWNvbnNvbGUvZGVmYXVsdC11c2VyLWF2YXRhci5wbmciLCJ3ZWJzaXRlIjpudWxsLCJiaXJ0aGRhdGUiOm51bGwsImdlbmRlciI6IlUiLCJ6b25laW5mbyI6bnVsbCwibG9jYWxlIjpudWxsLCJ1cGRhdGVkX2F0IjoiMjAyMy0wMi0xNFQwOToyNjoyOC4wNjhaIiwiZW1haWwiOm51bGwsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwicGhvbmVfbnVtYmVyIjoiMTg1MTY4Mjk5OTUiLCJwaG9uZV9udW1iZXJfdmVyaWZpZWQiOnRydWUsInVzZXJuYW1lIjpudWxsfQ.GweoWBCEyHQGP6G9ohbfBMUMALlbZMM9hRAes1De7BM\",\n\"refresh_token\": \"KanvCEmonS_FgCRdFftOCwka2f8Qjj4tcsIfJF-VC1W\"\n} \n
\n

\u54cd\u5e94\u793a\u4f8b\uff08\u5931\u8d25\uff09

\n
{\n \"error\": \"invalid_grant\",\n \"error_description\": \"\u6388\u6743\u7801\u65e0\u6548\u6216\u5df2\u8fc7\u671f\"\n}\n
\n

1.3.5 \u6240\u9700\u8c03\u7528\u63a5\u53e3\u5217\u8868

\n

GET${host}/oidc/me \u83b7\u53d6\u7528\u6237\u4fe1\u606f\n\u6b64\u7aef\u70b9\u662f OIDC \u83b7\u53d6\u7528\u6237\u7aef\u70b9\uff0c\u53ef\u4ee5\u901a\u8fc7 AccessToken \u83b7\u53d6\u6709\u5173\u5f53\u524d\u767b\u5f55\u7528\u6237\u7684\u4fe1\u606f\u3002

\n

\u8bf7\u6c42\u53c2\u6570\n\"\u56fe\u7247\"\n\u8bf7\u6c42\u793a\u4f8b

\n
curl --location --request GET 'https://{host}/oidc/me?access_token={access_token}' \n
\n

\u54cd\u5e94\u793a\u4f8b\uff08\u6210\u529f\uff09

\n
{\n \"name\": null,\n \"given_name\": null,\n \"middle_name\": null,\n \"family_name\": null,\n \"nickname\": null,\n \"preferred_username\": null,\n \"profile\": null,\n \"picture\": \"https://files.authing.co/authing-console/default-user-avatar.png\",\n \"website\": null,\n \"birthdate\": null,\n \"gender\": \"U\",\n \"zoneinfo\": null,\n \"locale\": null,\n \"updated_at\": \"2023-02-14T09:26:28.068Z\",\n \"email\": \"xxx@authing.cn\",\n \"email_verified\": true,\n \"phone_number\": \"185xxxx9995\",\n \"phone_number_verified\": true,\n \"username\": \"neo\",\n \"sub\": \"63eb53c441a5c2f05f24bb03\"\n}\n
\n

\u54cd\u5e94\u793a\u4f8b\uff08\u5931\u8d25\uff09

\n
{\n \"error\": \"invalid_grant\",\n \"error_description\": \"Access Token \u65e0\u6548\"\n}\n
\n

1.3.6 \u6821\u9a8c Token

\n

POST${host}/oidc/auth\n\u6b64\u7aef\u70b9\u63a5\u53d7 access_token \u3001id_token \u3001refresh_token \uff0c\u5e76\u8fd4\u56de\u4e00\u4e2a\u5e03\u5c14\u503c\uff0c\u6307\u793a\u5b83\u662f\u5426\u5904\u4e8e\u6d3b\u52a8\u72b6\u6001\u3002\u5982\u679c\u4ee4\u724c\u5904\u4e8e\u6d3b\u52a8\u72b6\u6001\uff0c\u8fd8\u5c06\u8fd4\u56de\u6709\u5173\u4ee4\u724c\u7684\u5176\u4ed6\u6570\u636e\u3002\u5982\u679c token \u65e0\u6548\u3001\u8fc7\u671f\u6216\u88ab\u540a\u9500\uff0c\u5219\u8ba4\u4e3a\u5b83\u5904\u4e8e\u975e\u6d3b\u52a8\u72b6\u6001\u3002

\n

access_token \u53ef\u4ee5\u4f7f\u7528 RS256 \u7b7e\u540d\u7b97\u6cd5\u6216 HS256 \u7b7e\u540d\u7b97\u6cd5\u8fdb\u884c\u7b7e\u540d\u3002\u4e0b\u9762\u662f\u8fd9\u4e24\u79cd\u7b7e\u540d\u7b97\u6cd5\u7684\u533a\u522b\uff1a

\n

RS256 \u662f\u4f7f\u7528 RSA \u7b97\u6cd5\u7684\u4e00\u79cd\u6570\u5b57\u7b7e\u540d\u7b97\u6cd5\uff0c\u5b83\u4f7f\u7528\u516c\u94a5 /\u79c1\u94a5\u5bf9\u6765\u52a0\u5bc6\u548c\u9a8c\u8bc1\u4fe1\u606f\u3002\nRS256 \u7b7e\u540d\u751f\u6210\u7684\u4ee4\u724c\u6bd4 HS256 \u7b7e\u540d\u751f\u6210\u7684\u4ee4\u724c\u66f4\u52a0\u5b89\u5168\uff0c\u56e0\u4e3a\u4f7f\u7528 RSA \u5bc6\u94a5\u5bf9\u8fdb\u884c\u7b7e\u540d\u53ef\u4ee5\u63d0\u4f9b\u66f4\u9ad8\u7684\u4fdd\u62a4\u7ea7\u522b\u3002\u4f7f\u7528 RS256 \u7b7e\u540d\u7b97\u6cd5\u7684\u4ee4\u724c\u53ef\u4ee5\u4f7f\u7528\u516c\u94a5\u8fdb\u884c\u9a8c\u8bc1\uff0c\u516c\u94a5\u53ef\u4ee5\u901a\u8fc7 JWK \u7aef\u70b9\u83b7\u53d6\u3002

\n

HS256 \u662f\u4f7f\u7528\u5bf9\u79f0\u5bc6\u94a5\u7684\u4e00\u79cd\u6570\u5b57\u7b7e\u540d\u7b97\u6cd5\u3002\u5b83\u4f7f\u7528\u540c\u4e00\u4e2a\u5bc6\u94a5\u8fdb\u884c\u7b7e\u540d\u548c\u9a8c\u8bc1\u3002\nHS256 \u7b7e\u540d\u7b97\u6cd5\u5728\u6027\u80fd\u65b9\u9762\u6bd4 RS256 \u7b7e\u540d\u7b97\u6cd5\u66f4\u5feb\uff0c\u56e0\u4e3a\u5b83\u4f7f\u7528\u7684\u662f\u5bf9\u79f0\u5bc6\u94a5\uff0c\u800c\u4e0d\u662f\u4f7f\u7528 RSA \u516c\u94a5 /\u79c1\u94a5\u5bf9\u6765\u7b7e\u540d\u548c\u9a8c\u8bc1\u3002\u4f7f\u7528 HS256 \u7b7e\u540d\u7b97\u6cd5\u7684\u4ee4\u724c\u53ef\u4ee5\u901a\u8fc7 shared secret \uff08\u5e94\u7528\u5bc6\u94a5\uff09\u8fdb\u884c\u9a8c\u8bc1\u3002

\n

\u5728\u5b9e\u9645\u5e94\u7528\u4e2d\uff0cRS256 \u7b97\u6cd5\u66f4\u52a0\u5b89\u5168\uff0c\u4f46\u540c\u65f6\u4e5f\u66f4\u52a0\u6d88\u8017\u8d44\u6e90\uff0c\u5982\u679c\u7cfb\u7edf\u9700\u8981\u9ad8\u6027\u80fd\uff0c\u53ef\u4ee5\u9009\u62e9 HS256 \u7b7e\u540d\u7b97\u6cd5\u3002

\n

\u9a8c\u8bc1 Token \u5206\u4e3a\u4e24\u79cd\u65b9\u5f0f

\n

\u672c\u5730\u9a8c\u8bc1\u4e0e\u4f7f\u7528 Authing \u5728\u7ebf\u9a8c\u8bc1\u3002\u6211\u4eec\u5efa\u8bae\u5728\u672c\u5730\u9a8c\u8bc1 JWT Token \uff0c\u56e0\u4e3a\u53ef\u4ee5\u8282\u7701\u4f60\u7684\u670d\u52a1\u5668\u5e26\u5bbd\u5e76\u52a0\u5feb\u9a8c\u8bc1\u901f\u5ea6\u3002\u4f60\u4e5f\u53ef\u4ee5\u9009\u62e9\u5c06 Token \u53d1\u9001\u5230 Authing \u7684\u9a8c\u8bc1\u63a5\u53e3\u7531 Authing \u8fdb\u884c\u9a8c\u8bc1\u5e76\u8fd4\u56de\u7ed3\u679c\uff0c\u4f46\u8fd9\u6837\u4f1a\u9020\u6210\u7f51\u7edc\u5ef6\u8fdf\uff0c\u800c\u4e14\u5728\u7f51\u7edc\u62e5\u585e\u65f6\u53ef\u80fd\u4f1a\u6709\u6162\u901f\u8bf7\u6c42\u3002

\n

\u4ee5\u4e0b\u662f\u672c\u5730\u9a8c\u8bc1\u548c\u5728\u7ebf\u9a8c\u8bc1\u7684\u4f18\u52a3\u5bf9\u6bd4\uff1a\n\"\u56fe\u7247\"

\n

\u5728\u7ebf\u6821\u9a8c

\n

\u9700\u8981\u6ce8\u610f\u7684\u662f\uff0cid_token \u76ee\u524d\u65e0\u6cd5\u5728\u7ebf\u6821\u9a8c\uff0c\u56e0\u4e3a id_token \u53ea\u662f\u4e00\u4e2a\u6807\u8bc6\uff0c\u82e5\u9700\u8981\u6821\u9a8c id_token \u5219\u9700\u8981\u60a8\u5728\u79bb\u7ebf\u81ea\u884c\u6821\u9a8c

\n

\u8bf7\u6c42\u53c2\u6570\n\"\u56fe\u7247\"

\n

\u8bf7\u6c42\u793a\u4f8b

\n
curl --location --request POST 'https://{host}/oidc/token/introspection' \\\n--header 'Content-Type: application/x-www-form-urlencoded' \\\n--data-urlencode 'client_id={\u5e94\u7528 ID}' \\\n--data-urlencode 'client_secret={\u5e94\u7528\u5bc6\u94a5}' \\\n--data-urlencode 'token={ token }' \\\n--data-urlencode 'token_type_hint={token_type_hint}'\n
\n

\u6821\u9a8c access_token \u54cd\u5e94\u793a\u4f8b\uff08\u6821\u9a8c\u901a\u8fc7\uff09

\n
{\n \"active\": true,\n \"sub\": \"63eb53c441a5c2f05f24bb03\",\n \"client_id\": \"63eb4585156d977101dd3750\",\n \"exp\": 1677648467,\n \"iat\": 1676438867,\n \"iss\": \"https://oidc-authorization-code.authing.cn/oidc\",\n \"jti\": \"ObgavGBUocr1wsrUvtDLHmuFSgoebxsiOY4JNRqIhaQ\",\n \"scope\": \"offline_access username profile openid phone email\",\n \"token_type\": \"Bearer\"\n}\n
\n

\u6821\u9a8c access_token \u54cd\u5e94\u793a\u4f8b\uff08\u6821\u9a8c\u672a\u901a\u8fc7\uff09

\n
{\n\"active\": false\n}\n
\n

\u6821\u9a8c refresh_token \u54cd\u5e94\u793a\u4f8b (\u6821\u9a8c\u901a\u8fc7)

\n
{\n \"active\": true,\n \"sub\": \"63eb53c441a5c2f05f24bb03\",\n \"client_id\": \"63eb4585156d977101dd3750\",\n \"exp\": 1679030867,\n \"iat\": 1676438867,\n \"iss\": \"https://oidc-authorization-code.authing.cn/oidc\",\n \"jti\": \"6F2TO1v1YZ1_N7I3jXYHjK-vZzKtlD0IiP5KPoUFUCQ\",\n \"scope\": \"offline_access username profile openid phone email\"\n}\n
\n

\u6821\u9a8c refresh_token \u54cd\u5e94\u793a\u4f8b\uff08\u6821\u9a8c\u672a\u901a\u8fc7\uff09

\n
{\n \"active\": false\n}\n
\n

\u79bb\u7ebf\u6821\u9a8c\n\u53ef\u53c2\u8003\u6587\u6863\uff08 Authing \u5f00\u53d1\u8005\u6587\u6863\uff09\uff1a\nhttps://docs.authing.cn/v2/guides/faqs/how-to-validate-user-token.html#%E6%9C%AC%E5%9C%B0%E9%AA%8C%E8%AF%81

\n

\u6211\u4eec\u7b80\u5355\u8bf4\u4e0b\uff0c\u82e5\u60a8\u4f7f\u7528\u79bb\u7ebf\u6821\u9a8c\u5e94\u8be5\u5bf9 token \u8fdb\u884c\u5982\u4e0b\u89c4\u5219\u7684\u6821\u9a8c\n1.\u683c\u5f0f\u6821\u9a8c\u00a0- \u6821\u9a8c token \u683c\u5f0f\u662f\u5426\u662f JWT \u683c\u5f0f\n2.\u7c7b\u578b\u6821\u9a8c\u00a0- \u6821\u9a8c token \u662f\u5426\u662f\u76ee\u6807 token \u7c7b\u578b\uff0c\u6bd4\u5982 access_token \u3001id_token \u3001refresh_token\n3.issuer \u6821\u9a8c\u00a0- \u6821\u9a8c token \u662f\u5426\u4e3a\u4fe1\u8d56\u7684 issuer \u9881\u53d1\n4.\u7b7e\u540d\u6821\u9a8c\u00a0- \u6821\u9a8c token \u7b7e\u540d\u662f\u5426\u7531 issuer \u7b7e\u53d1\uff0c\u9632\u6b62\u4f2a\u9020\n5.\u6709\u6548\u671f\u6821\u9a8c\u00a0- \u6821\u9a8c token \u662f\u5426\u5728\u6709\u6548\u671f\u5185\n6.claims \u6821\u9a8c\u00a0- \u662f\u5426\u7b26\u5408\u4e0e\u9884\u671f\u7684\u4e00\u81f4

\n

\u793a\u4f8b\u4ee3\u7801\n\u4e0b\u9762\u662f\u4e00\u4e2a\u793a\u4f8b Java \u4ee3\u7801\uff0c\u53ef\u4ee5\u7528\u4e8e\u5728\u672c\u5730\u6821\u9a8c OIDC RS256 \u548c HS256 \u7b7e\u53d1\u7684 access_token

\n
import com.nimbusds.jose.JWSObject;\nimport com.nimbusds.jwt.JWTClaimsSet;\nimport com.nimbusds.jwt.SignedJWT;\nimport java.net.URL;\nimport java.text.ParseException;\nimport java.util.Date;\npublic class OIDCValidator {\n private static final String ISSUER = \"https://your-issuer.com\";\n private static final String AUDIENCE = \"your-client-id\";\n private final URL jwkUrl;\n public OIDCValidator(final URL jwkUrl) {\n this.jwkUrl = jwkUrl;\n }\n public JWTClaimsSet validateToken(final String accessToken) throws ParseException {\n final SignedJWT signedJWT = SignedJWT.parse(accessToken);\n if (signedJWT == null) {\n throw new RuntimeException(\"Access token is null or empty\");\n }\n final JWTClaimsSet claims = signedJWT.getJWTClaimsSet();\n if (claims == null) {\n throw new RuntimeException(\"No claims present in the access token\");\n }\n if (!claims.getIssuer().equals(ISSUER)) {\n throw new RuntimeException(\"Invalid issuer in access token\");\n }\n if (!claims.getAudience().contains(AUDIENCE)) {\n throw new RuntimeException(\"Invalid audience in access token\");\n }\n final JWSObject jwsObject = signedJWT.getJWSObject();\n if (jwsObject == null) {\n throw new RuntimeException(\"No JWS object found in the access token\");\n }\n // Fetch the JWKs from the JWK set URL\n final JWKSet jwkSet = JWKSet.load(jwkUrl);\n final JWK jwk = jwkSet.getKeyByKeyId(jwsObject.getHeader().getKeyID());\n if (jwk == null) {\n throw new RuntimeException(\"No JWK found for the access token\");\n }\n if (!jwsObject.verify(jwk.getKey())) {\n throw new RuntimeException(\"Invalid signature in access token\");\n }\n if (claims.getExpirationTime() == null || claims.getExpirationTime().before(new Date())) {\n throw new RuntimeException(\"Expired access token\");\n }\n return claims;\n }\n}\n\n
\n

\u8fd9\u6bb5\u4ee3\u7801\u4f7f\u7528 Nimbus JOSE+JWT \u5e93\u6765\u89e3\u6790\u548c\u9a8c\u8bc1 JWT token \u3002\u5b83\u4f7f\u7528\u6307\u5b9a\u7684 issuer \u548c audience \u503c\u5bf9 access_token \u8fdb\u884c\u9a8c\u8bc1\uff0c\u5e76\u9a8c\u8bc1 JWT \u4e2d claims \u7684\u683c\u5f0f\u3001\u7c7b\u578b\u3001\u7b7e\u540d\u3001\u6709\u6548\u671f\u548c issuer \u3002\u5982\u679c\u53d1\u751f\u4efb\u4f55\u9a8c\u8bc1\u9519\u8bef\uff0c\u5219\u5c06\u629b\u51fa RuntimeException \u3002\u4f7f\u7528\u65f6\u9700\u8981\u4f20\u5165\u5bf9\u5e94\u7684 JWK URL \u548c access_token \u8fdb\u884c\u8c03\u7528\uff0c\u4f8b\u5982\uff1a

\n
final URL jwkUrl = new URL(\"https://your-issuer.com/.well-known/jwks.json\");\nfinal OIDCValidator validator = new OIDCValidator(jwkUrl);\nfinal String accessToken = \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjE1MTYyMzkwMjJ9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c\";\nfinal JWTClaimsSet claims = validator.validateToken(accessToken);\n
\n

\u8fd9\u4e2a\u793a\u4f8b\u53ea\u6821\u9a8c\u4e86 RS256 \u548c HS256 \u7b7e\u540d\u7b97\u6cd5\u3002

\n

1.3.7 \u5237\u65b0 Token

\n

POST${host}/oidc/token\n\u6b64\u529f\u80fd\u7528\u4e8e\u7528\u6237 token \u7684\u5237\u65b0\u64cd\u4f5c\uff0c\u5728 token \u83b7\u53d6\u9636\u6bb5\u9700\u8981\u5148\u83b7\u53d6\u5230 refresh_token \u3002

\n

\u8bf7\u6c42\u53c2\u6570\n\"\u56fe\u7247\"\n\u8bf7\u6c42\u53c2\u6570

\n
curl --location --request POST 'https://{host}/oidc/token' \\\n--header 'Content-Type: application/x-www-form-urlencoded' \\\n--data-urlencode 'client_id={\u5e94\u7528 ID}' \\\n--data-urlencode 'client_secret={\u5e94\u7528\u5bc6\u94a5}' \\\n--data-urlencode 'refresh_token={\u5237\u65b0\u4ee4\u724c}' \\\n--data-urlencode 'grant_type=refresh_token'\n
\n

\u54cd\u5e94\u793a\u4f8b(\u6210\u529f)

\n
{\n \"refresh_token\": \"6F2TO1v1YZ1_N7I3jXYHjK-vZzKtlD0IiP5KPoUFUCQ\",\n \"scope\": \"offline_access username profile openid phone email\",\n \"token_type\": \"Bearer\",\n \"access_token\": \"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6ImVtSzBGbVRIa0xlQWFjeS1YWEpVT3J6SzkxV243TkdoNGFlYUVlSjVQOUUifQ.eyJzdWIiOiI2M2ViNTNjNDQxYTVjMmYwNWYyNGJiMDMiLCJhdWQiOiI2M2ViNDU4NTE1NmQ5NzcxMDFkZDM3NTAiLCJzY29wZSI6Im9mZmxpbmVfYWNjZXNzIHVzZXJuYW1lIHByb2ZpbGUgb3BlbmlkIHBob25lIGVtYWlsIiwiaWF0IjoxNjc2NDQ0MjY4LCJleHAiOjE2Nzc2NTM4NjgsImp0aSI6IkEtZUlQYkJ5N3lJLTliUmp1RnJHeXNCSXdjbWtOUl9WalpYODB2aU05VFkiLCJpc3MiOiJodHRwczovL29pZGMtYXV0aG9yaXphdGlvbi1jb2RlLmF1dGhpbmcuY24vb2lkYyJ9.Kk3jSK5BSUEDVTQMdMAdG5cBCxZt31vQiD-XYHNA84Gd3Mo8eDLcQpjMEzQ8HJ4_b9IgMOz5ydXz0zAQ6AjLMW3Rl49qhTGDB7Kq7tHTFmDO8itoO2LQTCLPCPtP3TkoOgptlFD_sd32nefH-HojNhuqwKw469Byw3xnW5xEs3wSuOoUdHwR2n9j1T1Zgp3e90xmBjbtbofQE1z0IWtCnrfJ9ujWsKXoN_7OAXbCTa-Ak_DhgLHU7xutQaaBOgD28lLLT5xclgBWfv7Leyx_kBnVGT5Jvo1tfA6AUEp6wJO4GUBzsijLefI04VDzBGypNuFJlw_jOhSp-SWxJjQSwQ\",\n \"expires_in\": 1209600,\n \"id_token\": \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiI2M2ViNTNjNDQxYTVjMmYwNWYyNGJiMDMiLCJhdWQiOiI2M2ViNDU4NTE1NmQ5NzcxMDFkZDM3NTAiLCJpYXQiOjE2NzY0NDQyNjgsImV4cCI6MTY3NzY1Mzg2OCwiaXNzIjoiaHR0cHM6Ly9vaWRjLWF1dGhvcml6YXRpb24tY29kZS5hdXRoaW5nLmNuL29pZGMiLCJuYW1lIjpudWxsLCJnaXZlbl9uYW1lIjpudWxsLCJtaWRkbGVfbmFtZSI6bnVsbCwiZmFtaWx5X25hbWUiOm51bGwsIm5pY2tuYW1lIjpudWxsLCJwcmVmZXJyZWRfdXNlcm5hbWUiOm51bGwsInByb2ZpbGUiOm51bGwsInBpY3R1cmUiOiJodHRwczovL2ZpbGVzLmF1dGhpbmcuY28vYXV0aGluZy1jb25zb2xlL2RlZmF1bHQtdXNlci1hdmF0YXIucG5nIiwid2Vic2l0ZSI6bnVsbCwiYmlydGhkYXRlIjpudWxsLCJnZW5kZXIiOiJVIiwiem9uZWluZm8iOm51bGwsImxvY2FsZSI6bnVsbCwidXBkYXRlZF9hdCI6IjIwMjMtMDItMTRUMDk6MjY6MjguMDY4WiIsImVtYWlsIjpudWxsLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsInBob25lX251bWJlciI6IjE4NTE2ODI5OTk1IiwicGhvbmVfbnVtYmVyX3ZlcmlmaWVkIjp0cnVlLCJ1c2VybmFtZSI6bnVsbH0.DGoJrzkgti44zw-MotVM1KpLxbJTzc5pfh-xYun_xDQ\"\n}\n
\n

\u54cd\u5e94\u793a\u4f8b(\u5931\u8d25)

\n
{\n \"error\": \"invalid_grant\",\n \"error_description\": \"Refresh Token \u65e0\u6548\u6216\u5df2\u8fc7\u671f\"\n}\n
\n

1.3.8 \u64a4\u56de Token

\n

POST${host}/oidc/auth

\n

\u64a4\u9500 access_token / refresh_token \u3002

\n

\u8bf7\u6c42\u53c2\u6570\n\"\u56fe\u7247\"\n\u8bf7\u6c42\u793a\u4f8b

\n
curl --location --request POST 'https://{host}/oidc/token/revocation' \\\n--header 'Content-Type: application/x-www-form-urlencoded' \\\n--data-urlencode 'client_id={\u5e94\u7528 ID}' \\\n--data-urlencode 'client_secret={\u5e94\u7528\u5bc6\u94a5}' \\\n--data-urlencode 'token= {token}' \\\n--data-urlencode 'token_type_hint={token_type_hint}'\n
\n

\u54cd\u5e94\u793a\u4f8b(\u6210\u529f)

\n

HTTP 200 OK

\n

\u54cd\u5e94\u793a\u4f8b(\u5931\u8d25)

\n
{\n \"error\": \"xxxx\",\n \"error_description\": \"xxxx\"\n}\n
\n

1.3.9 \u7528\u6237\u767b\u51fa

\n

GET${host}/oidc/session/end\n\u4f7f\u7528\u6b64\u64cd\u4f5c\u901a\u8fc7\u5220\u9664\u7528\u6237\u7684\u6d4f\u89c8\u5668\u4f1a\u8bdd\u6765\u6ce8\u9500\u7528\u6237\u3002\npost_logout_redirect_uri \u53ef\u4ee5\u6307\u5b9a\u5728\u6267\u884c\u6ce8\u9500\u540e\u91cd\u5b9a\u5411\u7684\u5730\u5740\u3002\u5426\u5219\uff0c\u6d4f\u89c8\u5668\u5c06\u91cd\u5b9a\u5411\u5230\u9ed8\u8ba4\u9875\u9762\n\u8bf7\u6c42\u53c2\u6570\n\"\u56fe\u7247\"\n\u8bf7\u6c42\u793a\u4f8b(\u6d4f\u89c8\u5668\u8bbf\u95ee\uff09

\n
GET https://oidc-authorization-code.authing.cn/oidc/session/end?id_token_hint={id_token}&post_logout_redirect_uri=http://localhost:8080/&state=1676452381\n
\n

02.\u672c\u7ae0\u603b\u7ed3

\n

\u672c\u7ae0\u6211\u4eec\u4ecb\u7ecd\u4e86 OIDC \u6388\u6743\u7801\u6a21\u5f0f\u7684\u63a5\u5165\u6d41\u7a0b\u4ee5\u53ca\u76f8\u5173\u63a5\u53e3\u7684\u8c03\u7528\u65b9\u5f0f\uff0c\u5bf9\u4e8e\u5c0f\u767d\u6765\u8bf4\u53ef\u80fd\u9700\u8981\u6574\u4f53\u8dd1\u4e00\u904d\u6d41\u7a0b\u624d\u80fd\u719f\u6089\uff0c\u6211\u4eec\u4e5f\u5efa\u8bae\u4f60 fork \u6211\u4eec\u7684 postman collection \u8dd1\u4e00\u904d\u6d41\u7a0b\uff0c\u5bf9 PKCE \u6a21\u5f0f\u4f60\u5c31\u57fa\u672c\u638c\u63e1\u5566\u3002\n\u63a5\u4e0b\u6765\u6211\u4eec\u8fd8\u4f1a\u4ecb\u7ecd OIDC \u7684\u6388\u6743\u7801+PKCE \u6d41\u7a0b\uff0c\u4ee5\u53ca\u63a5\u5165\u00a0Authing\u00a0\u7684\u65b9\u5f0f\uff0c\u9700\u8981\u4f60\u5bf9\u6388\u6743\u7801\u6a21\u5f0f\u7684\u6d41\u7a0b\u6709\u4e00\u5b9a\u4e86\u89e3\u54e6\u3002

\n

\u5f80\u671f\u7cbe\u5f69\u5185\u5bb9\n\u4ec0\u4e48\u662f\u4e8b\u4ef6\u9a71\u52a8\uff08 EDA \uff09\uff1f\u4e3a\u4ec0\u4e48\u5b83\u662f\u6280\u672f\u9886\u57df\u7684\u4e3b\u8981\u9a71\u52a8\u529b\uff1f\n\"\u56fe\u7247\"

\n" }, { "author": { "url": "member/Authing", "name": "Authing", "avatar": "https://cdn.v2ex.com/avatar/b759/896b/570457_large.png?m=1683190646" }, "url": "t/922672", "title": "OIDC & OAuth2.0 \u534f\u8bae\u53ca\u5176\u6388\u6743\u6a21\u5f0f\u8be6\u89e3\uff5c\u8ba4\u8bc1\u534f\u8bae\u6700\u4f73\u5b9e\u8df5\u7cfb\u5217 [1]", "id": "t/922672", "date_published": "2023-03-09T11:01:17+00:00", "content_html": "

OIDC / OAuth2.0 \u662f\u4e00\u79cd\u5f00\u653e\u7684\u6807\u51c6\uff0c\u53ef\u4ee5\u5e2e\u52a9\u5e94\u7528\u7a0b\u5e8f\u5b89\u5168\u5730\u8bbf\u95ee\u7528\u6237\u7684\u8d44\u6e90\uff0c\u800c\u65e0\u9700\u5c06\u7528\u6237\u7684\u51ed\u636e\uff08\u5982\u7528\u6237\u540d\u548c\u5bc6\u7801\uff09\u66b4\u9732\u7ed9\u5e94\u7528\u7a0b\u5e8f\uff0c\u6211\u4eec\u53ef\u4ee5\u901a\u8fc7\u6807\u51c6\u534f\u8bae\uff0c\u5efa\u7acb\u96c6\u4e2d\u7684\u7528\u6237\u76ee\u5f55\u548c\u7edf\u4e00\u8ba4\u8bc1\u4e2d\u5fc3\uff0c\u5c06\u5185\u5916\u90e8\u4e1a\u52a1\u7cfb\u7edf\u7684\u767b\u5f55\u8ba4\u8bc1\u7edf\u4e00\u5230\u8ba4\u8bc1\u4e2d\u5fc3\uff0c\u5b9e\u73b0\u96c6\u4e2d\u5316\u7684\u7ba1\u7406\uff0c\u4ece\u800c\u907f\u514d\u6bcf\u5957\u4e1a\u52a1\u7cfb\u7edf\u90fd\u8981\u642d\u5efa\u4e00\u5957\u7528\u6237\u4f53\u7cfb\u6240\u9020\u6210\u7684\u7ba1\u7406\u4fa7\u4e0d\u4fbf\u53ca\u5b89\u5168\u4fa7\u7684\u98ce\u9669\u3002

\n

\u672c\u6587\u5c06\u5e26\u5404\u4f4d\u8be6\u7ec6\u4e86\u89e3 OAuth 2.0 & OIDC \u53ca\u5176\u6388\u6743\u6a21\u5f0f\u3002

\n

01 \u534f\u8bae\u4ecb\u7ecd

\n

1.1 OAuth 2.0 & OIDC

\n

OAuth 2.0 \u662f\u4e00\u4e2a\u6388\u6743\u6846\u67b6\uff0c\u4f7f\u5e94\u7528\u7a0b\u5e8f\u80fd\u591f\u83b7\u5f97\u5bf9 HTTP \u670d\u52a1\u4e0a\u7528\u6237\u5e10\u6237\u7684\u6709\u9650\u8bbf\u95ee\u6743\u9650\uff0c\u4f8b\u5982 Facebook \u3001GitHub \u548c DigitalOcean \u3002\u5b83\u901a\u8fc7\u5c06\u7528\u6237\u8ba4\u8bc1\u59d4\u6258\u7ed9\u6258\u7ba1\u7528\u6237\u5e10\u6237\u7684\u670d\u52a1\uff0c\u5e76\u6388\u6743\u7b2c\u4e09\u65b9\u5e94\u7528\u7a0b\u5e8f\u8bbf\u95ee\u7528\u6237\u5e10\u6237\u6765\u5b9e\u73b0\u3002

\n

OpenID Connect (OIDC) \u662f\u5efa\u7acb\u5728 OAuth 2.0 \u6846\u67b6\u4e4b\u4e0a\u7684\u7b80\u5355\u8eab\u4efd\u5c42\u3002\u5b83\u5728 OAuth 2.0 \u63d0\u4f9b\u7684\u6388\u6743\u7684\u57fa\u7840\u4e0a\u6dfb\u52a0\u4e86\u8ba4\u8bc1\u3002

\n

\u521d\u770b\u4e0a\u9762\u8fd9\u6bb5\u8bdd\u4f60\u53ef\u80fd\u5f88\u96be\u7406\u89e3\uff0c\u8fd9\u91cc\u7528\u767d\u8bdd\u89e3\u91ca\u4e0b\uff0cOAuth 2.0 \u5728\u8bbe\u8ba1\u4e4b\u521d\uff0c\u662f\u4e3a\u4e86 API \u5b89\u5168\u7684\u95ee\u9898\uff0c\u5b83\u662f\u4e00\u4e2a\u6388\u6743\u534f\u8bae\uff0c\u800c OIDC \u5219\u5728 OAuth2.0 \u534f\u8bae\u7684\u57fa\u7840\u4e0a\uff0c\u63d0\u4f9b\u4e86\u7528\u6237\u8ba4\u8bc1\u3001\u83b7\u53d6\u7528\u6237\u4fe1\u606f\u7b49\u7684\u6807\u51c6\u5b9e\u73b0\uff0c\u5f53\u7136\u6211\u4eec\u4e5f\u53ef\u4ee5\u7406\u89e3\u83b7\u53d6\u7528\u6237\u4fe1\u606f\u4e5f\u662f\u4e00\u4e2a API \uff0c\u7528 OAuth 2.0 \u4e5f\u6ca1\u95ee\u9898\u7684\uff0c\u8003\u8651\u5230\u8bfb\u8005\u7684\u611f\u53d7\uff0c\u5728\u8fd9\u91cc\u4e0d\u8981\u8fc7\u4e8e\u7ea0\u7ed3\uff0c\u53ea\u8981\u8bb0\u4f4f OIDC \u662f\u5b8c\u5168\u517c\u5bb9 OAuth2.0 \u7684\uff0c\u6211\u4eec\u73b0\u5728\u4e5f\u63a8\u8350\u7528 OIDC\u3002

\n

1.2 \u672f\u8bed\u4ecb\u7ecd

\n

\"\"

\n

\"\"

\n

\u5565\u5565\u5565\uff0c\u5199\u7684\u8fd9\u90fd\u662f\u5565\uff0c\u5c0f\u767d\u770b\u5230\u8fd9\u4e9b\u8111\u888b\u90fd\u5927\u4e86\uff0c\u6211\u5728\u8fd9\u91cc\u91cd\u70b9\u8bf4\u4e0b OIDC/OAuth2.0 \u534f\u8bae\u4ea4\u4e92\u65f6\u6240\u53c2\u4e0e\u7684\u51e0\u4e2a\u89d2\u8272\uff0c\u7b49\u4f60\u5bf9\u534f\u8bae\u719f\u6089\u4e86\uff0c\u53ef\u4ee5\u53cd\u8fc7\u5934\u6765\u518d\u770b\u4e0b\u76f8\u5173\u7684\u4ecb\u7ecd\uff0c\u5728\u63a5\u4e0b\u6765\u7684\u6388\u6743\u6a21\u5f0f\u4ecb\u7ecd\u4e2d\uff0c\u6211\u4eec\u4f1a\u7ed3\u5408\u8fd9\u56db\u4e2a\u89d2\u8272\uff0c\u4ecb\u7ecd\u4e0b\u4e0d\u540c\u6388\u6743\u6a21\u5f0f\u7684\u6d41\u7a0b\u3002

\n\n

1.3 Client \u7c7b\u578b\u4ecb\u7ecd

\n

OAuth2.0 / OIDC \u4e2d\u5b9a\u4e49\u4e86 2 \u79cd Client \u7c7b\u578b\uff1a

\n

\"\"

\n

\u6211\u4eec\u5728\u8fd9\u91cc\u89e3\u91ca\u4e0b\uff1a

\n

Confidential Clients \u673a\u5bc6\u578b\u5e94\u7528\uff1a\u80fd\u591f\u5b89\u5168\u7684\u5b58\u50a8\u51ed\u8bc1\uff08 client_secret \uff09\uff0c\u4f8b\u5982\u6709\u540e\u7aef\u670d\u52a1\uff0c\u4f60\u7684\u524d\u7aef\u662f Vue \uff0c\u540e\u53f0\u662f Java \uff0c\u90a3\u4e48\u53ef\u4ee5\u7406\u89e3\u4e3a\u673a\u5bc6\u6027\u5e94\u7528\uff0c\u56e0\u4e3a\u4f60\u7684\u540e\u7aef\u80fd\u591f\u5b89\u5168\u7684\u4fdd\u5b58 client_secret \uff0c\u800c\u4e0d\u4f1a\u5c06 client_secret \u76f4\u63a5\u66b4\u9732\u7ed9\u7528\u6237\uff0c\u6b64\u65f6\u4f60\u53ef\u4ee5\u4f7f\u7528\u6388\u6743\u7801\u6a21\u5f0f\u3002

\n

Public Clients \u516c\u5171\u578b\u5e94\u7528\uff1a\u65e0\u6cd5\u5b89\u5168\u5b58\u50a8\u51ed\u8bc1\uff08 Client Secrets \uff09\uff0c\u4f8b\u5982 SPA \u3001\u79fb\u52a8\u7aef\u3001\u6216\u8005\u5b8c\u5168\u524d\u540e\u7aef\u5206\u79bb\u7684\u5e94\u7528\uff0c\u5e94\u5f53\u4f7f\u7528\u6388\u6743\u7801 + PKCE \u6a21\u5f0f

\n

1.4 OIDC \u6388\u6743\u6a21\u5f0f\u4e0e\u9009\u578b\u5efa\u8bae

\n

\u91cd\u70b9\u6765\u5566\uff01\u6211\u4eec\u8981\u4e86\u89e3\u6388\u6743\u6a21\u5f0f\uff0c\u624d\u80fd\u66f4\u597d\u7684\u9488\u5bf9\u7cfb\u7edf\u7c7b\u578b\u8fdb\u884c\u6388\u6743\u6a21\u5f0f\u7684\u9009\u578b\uff0c\u907f\u514d\u7531\u4e8e\u6388\u6743\u6a21\u5f0f\u9009\u578b\u4e0d\u5f53\u6240\u9020\u6210\u7684\u5f00\u53d1\u5de5\u4f5c\u589e\u52a0\u548c\u5b89\u5168\u4fa7\u7684\u6f0f\u6d1e\u3002

\n\n

02 \u6388\u6743\u6a21\u5f0f\u8be6\u7ec6\u4ecb\u7ecd

\n

2.1 \u6388\u6743\u7801\u6a21\u5f0f\uff08 Authorization Code \uff09

\n

\u6388\u6743\u7801\u6a21\u5f0f\u9002\u5408\u5e94\u7528\u5177\u5907\u540e\u7aef\u670d\u52a1\u5668\u7684\u573a\u666f\u3002\u6388\u6743\u7801\u6a21\u5f0f\u8981\u6c42\u5e94\u7528\u5fc5\u987b\u80fd\u591f\u5b89\u5168\u5b58\u50a8\u5bc6\u94a5\uff0c\u7528\u4e8e\u540e\u7eed\u4f7f\u7528\u6388\u6743\u7801\u6362 Access Token \u3002\u6388\u6743\u7801\u6a21\u5f0f\u9700\u8981\u901a\u8fc7\u6d4f\u89c8\u5668\u4e0e\u7ec8\u7aef\u7528\u6237\u4ea4\u4e92\u5b8c\u6210\u8ba4\u8bc1\u6388\u6743\uff0c\u7136\u540e\u901a\u8fc7\u6d4f\u89c8\u5668\u91cd\u5b9a\u5411\u5c06\u6388\u6743\u7801\u53d1\u9001\u5230\u540e\u7aef\u670d\u52a1\uff0c\u4e4b\u540e\u8fdb\u884c\u6388\u6743\u7801\u6362 Token \u4ee5\u53ca Token \u6362\u7528\u6237\u4fe1\u606f\u3002

\n

\u6574\u4f53\u4e0a\uff0c\u6709\u4ee5\u4e0b\u6d41\u7a0b\uff1a

\n
    \n
  1. \u5728\u4f60\u7684\u5e94\u7528\u4e2d\uff0c\u8ba9\u7528\u6237\u8bbf\u95ee\u767b\u5f55\u94fe\u63a5\uff0c\u6d4f\u89c8\u5668\u8df3\u8f6c\u5230 Authing \uff0c\u7528\u6237\u5728 Authing \u5b8c\u6210\u8ba4\u8bc1\u3002
  2. \n
  3. \u6d4f\u89c8\u5668\u63a5\u6536\u5230\u4e00\u4e2a\u4ece Authing \u670d\u52a1\u5668\u53d1\u6765\u7684\u6388\u6743\u7801\u3002
  4. \n
  5. \u6d4f\u89c8\u5668\u901a\u8fc7\u91cd\u5b9a\u5411\u5c06\u6388\u6743\u7801\u53d1\u9001\u5230\u4f60\u7684\u5e94\u7528\u540e\u7aef\u3002
  6. \n
  7. \u4f60\u7684\u5e94\u7528\u670d\u52a1\u5c06\u6388\u6743\u7801\u53d1\u9001\u5230 Authing \u83b7\u53d6 AccessToken \u548c IdToken \uff0c\u5982\u679c\u9700\u8981\uff0c\u8fd8\u4f1a\u8fd4\u56de refresh token \u3002
  8. \n
  9. \u4f60\u7684\u5e94\u7528\u540e\u7aef\u73b0\u5728\u77e5\u9053\u4e86\u7528\u6237\u7684\u8eab\u4efd\uff0c\u540e\u7eed\u53ef\u4ee5\u4fdd\u5b58\u7528\u6237\u4fe1\u606f\uff0c\u91cd\u5b9a\u5411\u5230\u524d\u7aef\u5176\u4ed6\u9875\u9762\uff0c\u4f7f\u7528 AccessToken \u8c03\u7528\u8d44\u6e90\u65b9\u7684\u5176\u4ed6 API \u7b49\u7b49\u3002
  10. \n
\n

\u6d41\u7a0b\u56fe\u5982\u4e0b\uff1a\n\"\"

\n

2.2 \u6388\u6743\u7801 + PKCE \u6a21\u5f0f\uff08 Authorization Code With PKCE \uff09

\n

\u5982\u679c\u4f60\u7684\u5e94\u7528\u662f\u4e00\u4e2a SPA \u524d\u7aef\u5e94\u7528\u6216\u79fb\u52a8\u7aef App \uff0c\u5efa\u8bae\u4f7f\u7528\u6388\u6743\u7801 + PKCE \u6a21\u5f0f\u6765\u5b8c\u6210\u7528\u6237\u7684\u8ba4\u8bc1\u548c\u6388\u6743\u3002\u6388\u6743\u7801 + PKCE \u6a21\u5f0f\u9002\u5408\u4e0d\u80fd\u5b89\u5168\u5b58\u50a8\u5bc6\u94a5\u7684\u573a\u666f\uff08\u4f8b\u5982\u524d\u7aef\u6d4f\u89c8\u5668) \u3002

\n

\u6211\u4eec\u89e3\u91ca\u4e0b code_verifier \u548c code_challenge \u3002

\n

code_verifier\uff1a\u5728 [A-Z] / [a-z] / [0-9] / \"-\" / \".\" / \"_\" / \"~\" \u8303\u56f4\u5185\uff0c\u751f\u6210 43-128 \u4f4d\u7684\u968f\u673a\u5b57\u7b26\u4e32\u3002\ncode_challenge\uff1a\u5219\u662f\u5bf9 code_verifier \u901a\u8fc7 code_challenge_method \u4f8b\u5982 sha256 \u8f6c\u6362\u5f97\u6765\u7684\u3002

\n

\u7528\u5927\u767d\u8bdd\u8bb2\u4e0b\u5c31\u662f\u5728\u8ba4\u8bc1\u662f\u7528\u6237\u643a\u5e26\u7684\u662f\u52a0\u5bc6\u540e\u7684 code_challenge \uff0c\u5728\u7528\u6237\u8ba4\u8bc1\u6210\u529f\u83b7\u53d6 Token \u65f6\uff0c\u5ba2\u6237\u7aef\u8bc1\u660e\u81ea\u5df1\u7684\u65b9\u5f0f\u5219\u662f\u628a code_verifier \u539f\u6587\u53d1\u9001\uff0c\u8ba4\u8bc1\u4e2d\u5fc3\u6536\u5230\u83b7\u53d6 Token \u8bf7\u6c42\u65f6\u901a\u8fc7 code_verifier + code_challenge_method \u8fdb\u884c\u8f6c\u6362\uff0c\u53d1\u73b0\u6700\u7ec8\u7ed3\u679c\u4e0e code_challenge \u5339\u914d\u5219\u8fd4\u56de Token \uff0c\u5426\u5219\u62d2\u7edd\u3002

\n

\u6574\u4f53\u4e0a\uff0c\u6709\u4ee5\u4e0b\u6d41\u7a0b:

\n
    \n
  1. \u5728\u4f60\u7684\u5e94\u7528\u4e2d\uff0c\u8ba9\u7528\u6237\u8bbf\u95ee\u767b\u5f55\u94fe\u63a5(\u5305\u542b code_challenge ) \uff0c\u6d4f\u89c8\u5668\u8df3\u8f6c\u5230 Authing \uff0c\u7528\u6237\u5728 Authing \u5b8c\u6210\u8ba4\u8bc1\u3002
  2. \n
  3. \u6d4f\u89c8\u5668\u63a5\u6536\u5230\u4e00\u4e2a\u4ece Authing \u670d\u52a1\u5668\u53d1\u6765\u7684\u6388\u6743\u7801\u3002
  4. \n
  5. \u6d4f\u89c8\u5668\u901a\u8fc7\u91cd\u5b9a\u5411\u5c06\u6388\u6743\u7801\u53d1\u9001\u5230\u4f60\u7684\u5e94\u7528\u524d\u7aef\u3002
  6. \n
  7. \u4f60\u7684\u5e94\u7528\u5c06\u6388\u6743\u7801\u548c code_verifier \u53d1\u9001\u5230 Authing \u83b7\u53d6 AccessToken \u548c IdToken \uff0c\u5982\u679c\u9700\u8981\uff0c\u8fd8\u4f1a\u8fd4\u56de Refresh token \u3002
  8. \n
  9. \u4f60\u7684\u5e94\u7528\u524d\u7aef\u73b0\u5728\u77e5\u9053\u4e86\u7528\u6237\u7684\u8eab\u4efd\uff0c\u540e\u7eed\u4f7f\u7528 Access token \u6362\u53d6\u7528\u6237\u4fe1\u606f\uff0c\u91cd\u5b9a\u5411\u5230\u524d\u7aef\u5176\u4ed6\u9875\u9762\uff0c\u4f7f\u7528 AccessToken \u8c03\u7528\u8d44\u6e90\u65b9\u7684\u5176\u4ed6 API \u7b49\u7b49\u3002
  10. \n
\n

\u6d41\u7a0b\u56fe\u5982\u4e0b\uff1a\n\"\"

\n

2.3 \u5ba2\u6237\u7aef\u51ed\u8bc1\u6a21\u5f0f\uff08 Client Credentials \uff09

\n

Client Credentials \u6a21\u5f0f\u7528\u4e8e\u8fdb\u884c\u670d\u52a1\u5668\u5bf9\u670d\u52a1\u5668\u95f4\u7684\u6388\u6743\uff08 M2M \u6388\u6743\uff09\uff0c\u671f\u95f4\u6ca1\u6709\u7528\u6237\u7684\u53c2\u4e0e\u3002\u4f60\u9700\u8981\u521b\u5efa\u7f16\u7a0b\u8bbf\u95ee\u8d26\u53f7\uff0c\u5e76\u5c06 AK \u3001SK \u5bc6\u94a5\u5bf9\u4ea4\u7ed9\u4f60\u7684\u8d44\u6e90\u8c03\u7528\u65b9\u3002

\n

\u6ce8\u610f\uff1aClient Credentials \u6a21\u5f0f\u4e0d\u652f\u6301 Refresh Token\u3002

\n

\u6574\u4f53\u4e0a\uff0c\u6709\u4ee5\u4e0b\u6d41\u7a0b\uff1a

\n
    \n
  1. \u8d44\u6e90\u8c03\u7528\u65b9\u5c06\u4ed6\u7684\u51ed\u8bc1 AK \u3001SK \u4ee5\u53ca\u9700\u8981\u8bf7\u6c42\u7684\u6743\u9650 scope \u53d1\u9001\u5230 Authing \u6388\u6743\u7aef\u70b9\u3002
  2. \n
  3. \u5982\u679c\u51ed\u8bc1\u6b63\u786e\uff0c\u5e76\u4e14\u8c03\u7528\u65b9\u5177\u5907\u8d44\u6e90\u6743\u9650\uff0cAuthing \u4e3a\u5176\u9881\u53d1 AccessToken \u3002
  4. \n
\n

\u6d41\u7a0b\u56fe\u5982\u4e0b\uff1a\n\"\"

\n

2.4 \u9690\u5f0f\u6a21\u5f0f\uff08 Implicit \uff09\uff08\u4e0d\u63a8\u8350\uff09

\n

\u9690\u5f0f\u6a21\u5f0f\u9002\u5408\u4e0d\u80fd\u5b89\u5168\u5b58\u50a8\u5bc6\u94a5\u7684\u573a\u666f\uff08\u4f8b\u5982\u524d\u7aef\u6d4f\u89c8\u5668\uff09\uff0c\u4e0d\u63a8\u8350\u6b64\u6a21\u5f0f\uff0c\u5efa\u8bae\u91c7\u7528\u5176\u4ed6\u6a21\u5f0f\u3002\u5728\u9690\u5f0f\u6a21\u5f0f\u4e2d\uff0c\u5e94\u7528\u4e0d\u9700\u8981\u4f7f\u7528 code \u6362 token \uff0c\u65e0\u9700\u8bf7\u6c42 /token \u7aef\u70b9\uff0cAccessToken \u548c IdToken \u4f1a\u76f4\u63a5\u4ece\u8ba4\u8bc1\u7aef\u70b9\u8fd4\u56de\u3002

\n

\u6ce8\u610f\uff1a\u56e0\u4e3a\u9690\u5f0f\u6a21\u5f0f\u7528\u4e8e\u4e0d\u80fd\u5b89\u5168\u5b58\u50a8\u5bc6\u94a5\u7684\u573a\u666f\uff0c\u6240\u4ee5\u9690\u5f0f\u6a21\u5f0f\u4e0d\u652f\u6301\u83b7\u53d6 Refresh Token\u3002

\n

\u6574\u4f53\u4e0a\uff0c\u6709\u4ee5\u4e0b\u6d41\u7a0b\uff1a

\n
    \n
  1. \u5728\u4f60\u7684\u5e94\u7528\u4e2d\uff0c\u8ba9\u7528\u6237\u8bbf\u95ee\u767b\u5f55\u94fe\u63a5\uff0c\u6d4f\u89c8\u5668\u8df3\u8f6c\u5230 Authing \uff0c\u7528\u6237\u5728 Authing \u5b8c\u6210\u8ba4\u8bc1\u3002
  2. \n
  3. Authing \u5c06\u6d4f\u89c8\u5668\u91cd\u5b9a\u5411\u5230\u4f60\u7684\u5e94\u7528\u56de\u8c03\u5730\u5740\uff0cAccessToken \u548c IdToken \u4f5c\u4e3a URL hash \u4f20\u9012\u3002
  4. \n
  5. \u4f60\u7684\u5e94\u7528\u4ece URL \u4e2d\u53d6\u51fa token \u3002
  6. \n
  7. \u4f60\u7684\u5e94\u7528\u53ef\u4ee5\u5c06 AccessToken \u4e0e IdToken \u4fdd\u5b58\uff0c\u4ee5\u4fbf\u540e\u7eed\u4f7f\u7528\uff0c\u4f8b\u5982\u643a\u5e26 AccessToken \u8bbf\u95ee\u8d44\u6e90\u670d\u52a1\u5668\uff0c\u643a\u5e26 IdToken \u8bf7\u6c42\u670d\u52a1\u7aef\u4ece\u800c\u670d\u52a1\u7aef\u80fd\u591f\u8fa8\u522b\u7528\u6237\u8eab\u4efd\u3002
  8. \n
\n

\u6d41\u7a0b\u56fe\u5982\u4e0b\uff1a

\n

\"\"

\n

2.5 \u5bc6\u7801\u6a21\u5f0f\uff08 Password \uff09\uff08\u4e0d\u63a8\u8350\uff09

\n

\u4e0d\u63a8\u8350\u4f7f\u7528\u6b64\u6a21\u5f0f\uff0c\u5c3d\u91cf\u4f7f\u7528\u5176\u4ed6\u6a21\u5f0f\u3002\u53ea\u6709\u5176\u4ed6\u6a21\u5f0f\u90fd\u65e0\u6cd5\u89e3\u51b3\u95ee\u9898\u65f6\u624d\u4f1a\u8003\u8651\u4f7f\u7528\u5bc6\u7801\u6a21\u5f0f\u3002\u5982\u679c\u4f7f\u7528\u5bc6\u7801\u6a21\u5f0f\uff0c\u8bf7\u786e\u4fdd\u4f60\u7684\u5e94\u7528\u4ee3\u7801\u903b\u8f91\u975e\u5e38\u5b89\u5168\uff0c\u4e0d\u4f1a\u88ab\u9ed1\u5ba2\u653b\u51fb\uff0c\u5426\u5219\u5c06\u4f1a\u76f4\u63a5\u6cc4\u9732\u7528\u6237\u7684\u8d26\u5bc6\u3002\u4e00\u822c\u7528\u4e8e\u6539\u9020\u96c6\u6210\u975e\u5e38\u53e4\u8001\u7684\u5e94\u7528\uff0c\u5426\u5219\u7edd\u5bf9\u4e0d\u8981\u628a\u5b83\u4f5c\u4e3a\u4f60\u7684\u7b2c\u4e00\u9009\u62e9\u3002

\n

\u6574\u4f53\u4e0a\uff0c\u6709\u4ee5\u4e0b\u6d41\u7a0b\uff1a

\n
    \n
  1. \u4f60\u7684\u5e94\u7528\u8ba9\u7528\u6237\u8f93\u5165\u8d26\u5bc6\u4fe1\u606f\u3002
  2. \n
  3. \u4f60\u7684\u5e94\u7528\u5c06\u7528\u6237\u8d26\u5bc6\u53d1\u9001\u5230 Authing \u3002
  4. \n
  5. \u5982\u679c\u8d26\u5bc6\u6b63\u786e\uff0cAuthing \u8fd4\u56de token \u3002
  6. \n
\n

\u6d41\u7a0b\u56fe\u5982\u4e0b\uff1a

\n

\"\"

\n

2.6 \u8bbe\u5907\u4ee3\u7801\u6a21\u5f0f\uff08 Device Code \uff09(\u51e0\u4e4e\u7528\u4e0d\u5230)

\n

\u5bf9\u4e8e\u4e00\u4e9b\u8fde\u63a5\u5230\u4e92\u8054\u7f51\u7684\u8f93\u5165\u53d7\u9650\u8bbe\u5907\uff0c\u8bbe\u5907\u4e0d\u4f1a\u76f4\u63a5\u9a8c\u8bc1\u7528\u6237\u8eab\u4efd\uff0c\u800c\u662f\u8ba9\u7528\u6237\u901a\u8fc7\u94fe\u63a5\u6216\u4e8c\u7ef4\u7801\u8f6c\u5230\u624b\u673a\u6216\u7535\u8111\u4e0a\u8fdb\u884c\u8ba4\u8bc1\uff0c\u4ece\u800c\u907f\u514d\u4e86\u7528\u6237\u65e0\u6cd5\u8f7b\u677e\u8f93\u5165\u6587\u672c\u6240\u5e26\u6765\u7684\u7cdf\u7cd5\u4f53\u9a8c\u3002

\n

Device Code Flow \u8fd9\u4e2a\u4e0e\u524d\u9762\u51e0\u4e2a\u4e0d\u592a\u4e00\u6837\uff0c\u5f00\u59cb\u4e0d\u518d\u662f\u7531\u8d44\u6e90\u6301\u6709\u8005\u53d1\u8d77\uff0c\u800c\u662f\u7531\u5ba2\u6237\u7aef\u5f00\u59cb\u3002\u751a\u81f3\u767b\u5f55\u7684\u65b9\u6cd5\u4e0e\u5ba2\u6237\u7aef\u8fd8\u6ca1\u6709\u7279\u522b\u7684\u5173\u8054\u3002

\n

\u5927\u81f4\u6d41\u7a0b\u8bf4\u660e\u5982\u4e0b\uff1a

\n
    \n
  1. \u5ba2\u6237\u7aef\u53d1\u8d77\u5411\u8ba4\u8bc1\u670d\u52a1\u5668\u53d6\u5f97 device_code \u548c user_code \u3002
  2. \n
  3. \u5ba2\u6237\u7aef\u901a\u8fc7\u4e8c\u7ef4\u7801\u6216\u8005\u5176\u4ed6\u65b9\u5f0f\u5c06 user_code \u4ea4\u7ed9\u8d44\u6e90\u6301\u6709\u8005\u3002
  4. \n
  5. \u8d44\u6e90\u6301\u6709\u8005\u900f\u8fc7\u67d0\u4e2a\u7aef\u70b9 (endpoint) \u4e0e user_code \u8fdb\u884c\u8ba4\u8bc1\u3002
  6. \n
  7. \u5ba2\u6237\u7aef\u901a\u8fc7 device_code \u8f6e\u8bad\u8ba4\u8bc1\u670d\u52a1\u5668\u662f\u5426\u6709\u4eba\u8ba4\u8bc1\uff0c\u82e5\u6709\u4eba\u8ba4\u8bc1\u5219\u4f1a\u8fd4\u56de access_token \u3002
  8. \n
\n

\u6d41\u7a0b\u56fe\u5982\u4e0b\uff1a

\n

\"\"

\n

\u4e00\u4e2a\u8bbe\u8ba1\u826f\u597d\u7684\u7cfb\u7edf\uff0c\u90fd\u9700\u8981\u4e00\u4e2a\u6807\u51c6\u3001\u5b89\u5168\u3001\u53ef\u6269\u5c55\u7684\u7528\u6237\u8ba4\u8bc1\u534f\u8bae\uff0c\u65e0\u8bba\u662f ToC \u8fd8\u662f ToE \uff0c\u63a5\u6765\u4e0b\u6211\u4eec\u8fd8\u4f1a\u9488\u5bf9\u5177\u4f53\u7684\u6388\u6743\u6a21\u5f0f\u7ed3\u5408\u5b9e\u9645\u573a\u666f\u8bb2\u4e00\u4e0b\u5177\u4f53\u7684\u6a21\u5f0f\u3002

\n

\u672c\u7ae0\u603b\u7ed3

\n
    \n
  1. \n

    \u672c\u7ae0\u6211\u4eec\u4ecb\u7ecd\u4e86 OIDC \u548c OAuth2.0 \u4e24\u4e2a\u534f\u8bae\uff0c\u5728\u4f7f\u7528\u8d77\u6765\uff0c\u8fd9\u4e24\u4e2a\u534f\u8bae\u5e76\u6ca1\u6709\u592a\u5927\u7684\u533a\u522b\uff0cOAuth2.0 \u662f\u4e00\u4e2a\u6388\u6743\u534f\u8bae\uff0cOIDC \u534f\u8bae\u5219\u662f\u5728 OAuth2.0 \u7684\u63d0\u4f9b\u7684\u6388\u6743\u7684\u57fa\u7840\u4e0a\u6dfb\u52a0\u4e86\u8ba4\u8bc1\u3002

    \n
  2. \n
  3. \n

    \u6388\u6743\u6a21\u5f0f\uff0c\u6211\u4eec\u5206\u522b\u4ecb\u7ecd\u4e86\u6388\u6743\u7801\u6a21\u5f0f\uff08 Authorization Code \uff09 \u3001\u6388\u6743\u7801 + PKCE \u6a21\u5f0f\uff08 Authorization Code With PKCE \uff09 \u3001\u5ba2\u6237\u7aef\u51ed\u8bc1\u6a21\u5f0f\uff08 Client Credentials \uff09 \u3001\u9690\u5f0f\u6a21\u5f0f\uff08 Implicit \uff09\uff08\u4e0d\u63a8\u8350\uff09\u3001\u5bc6\u7801\u6a21\u5f0f\uff08 Password \uff09 \uff08\u4e0d\u63a8\u8350\uff09\u3001\u8bbe\u5907\u4ee3\u7801\u6a21\u5f0f\uff08 Device Code \uff09(\u51e0\u4e4e\u7528\u4e0d\u5230) \u3002

    \n
  4. \n
  5. \n

    \u6388\u6743\u6a21\u5f0f\u9009\u62e9

    \n
  6. \n
\n\n" }, { "author": { "url": "member/Authing", "name": "Authing", "avatar": "https://cdn.v2ex.com/avatar/b759/896b/570457_large.png?m=1683190646" }, "url": "t/920916", "title": "OIDC & OAuth2.0 \u8ba4\u8bc1\u534f\u8bae\u6700\u4f73\u5b9e\u8df5\u7cfb\u5217 02 - \u6388\u6743\u7801\u6a21\u5f0f\uff08Authorization Code\uff09\u63a5\u5165 Authing", "id": "t/920916", "date_published": "2023-03-03T11:00:02+00:00", "content_html": "

\u5728\u4e0a\u4e00\u7bc7\u6587\u7ae0\u4e2d\uff0c\u6211\u4eec\u6574\u4f53\u4ecb\u7ecd OIDC / OAuth2.0 \u534f\u8bae\uff0c\u672c\u6b21\u6211\u4eec\u5c06\u91cd\u70b9\u56f4\u7ed5\u6388\u6743\u7801\u6a21\u5f0f\uff08 Authorization Code \uff09\u4ee5\u53ca\u63a5\u5165 Authing \u8fdb\u884c\u4ecb\u7ecd\uff0c\u4ece\u800c\u8ba9\u4f60\u7684\u7cfb\u7edf\u5feb\u901f\u5177\u5907\u63a5\u5165\u7528\u6237\u8ba4\u8bc1\u7684\u6807\u51c6\u4f53\u7cfb\u3002

\n

\u63a5\u5165 Authing \u540e\u7684\u4f18\u52bf\uff1a\n\u5728\u6574\u4e2a Authing \u7684\u8eab\u4efd\u6e90\u4e2d\uff0c\u5df2\u7ecf\u5305\u542b\u4e86\u793e\u4f1a\u5316\u767b\u5f55\u65b9\u5f0f \u5fae\u4fe1\u3001\u5fae\u535a\u3001QQ \u3001FB \u3001TW ...\u7b49\u7b49\uff0c\u4f01\u4e1a\u767b\u5f55\u65b9\u5f0f \u98de\u4e66\u3001\u9489\u9489\u3001\u4f01\u5fae\u3001AD \u7b49\u7b49\uff0c\u53ea\u8981\u4f60\u5b8c\u6210\u4e86\u63a5\u5165 Authing \u5c31\u610f\u5473\u7740\u4f60\u7684\u4e1a\u52a1\u7cfb\u7edf\u5177\u5907\u4e86\u8fd9\u4e9b\u80fd\u529b\u3002

\n

01 \u6388\u6743\u7801\u6a21\u5f0f\uff08 Authorization Code \uff09

\n

1.1 \u6574\u4f53\u6d41\u7a0b

\n

\u6574\u4f53\u4e0a\uff0c\u6709\u4ee5\u4e0b\u6d41\u7a0b\uff1a

\n
    \n
  1. \u5728\u4f60\u7684\u5e94\u7528\u4e2d\uff0c\u8ba9\u7528\u6237\u8bbf\u95ee\u767b\u5f55\u94fe\u63a5\uff0c\u6d4f\u89c8\u5668\u8df3\u8f6c\u5230 Authing \uff0c\u7528\u6237\u5728 Authing \u5b8c\u6210\u8ba4\u8bc1\u3002
  2. \n
  3. \u6d4f\u89c8\u5668\u63a5\u6536\u5230\u4e00\u4e2a\u4ece Authing \u670d\u52a1\u5668\u53d1\u6765\u7684\u6388\u6743\u7801\u3002
  4. \n
  5. \u6d4f\u89c8\u5668\u901a\u8fc7\u91cd\u5b9a\u5411\u5c06\u6388\u6743\u7801\u53d1\u9001\u5230\u4f60\u7684\u5e94\u7528\u540e\u7aef\u3002
  6. \n
  7. \u4f60\u7684\u5e94\u7528\u670d\u52a1\u5c06\u6388\u6743\u7801\u53d1\u9001\u5230 Authing \u83b7\u53d6 AccessToken \u548c IdToken \uff0c\u5982\u679c\u9700\u8981\uff0c\u8fd8\u4f1a\u8fd4\u56de refresh token \u3002
  8. \n
  9. \u4f60\u7684\u5e94\u7528\u540e\u7aef\u73b0\u5728\u77e5\u9053\u4e86\u7528\u6237\u7684\u8eab\u4efd\uff0c\u540e\u7eed\u53ef\u4ee5\u4fdd\u5b58\u7528\u6237\u4fe1\u606f\uff0c\u91cd\u5b9a\u5411\u5230\u524d\u7aef\u5176\u4ed6\u9875\u9762\uff0c\u4f7f\u7528 AccessToken \u8c03\u7528\u8d44\u6e90\u65b9\u7684\u5176\u4ed6 API \u7b49\u7b49\u3002
  10. \n
\n

\u6d41\u7a0b\u56fe\u5982\u4e0b\uff1a\n\"\"

\n

1.2 \u51c6\u5907\u63a5\u5165

\n\n

\u521b\u5efa\u5e94\u7528\uff1a

\n

\"\"

\n

\u914d\u7f6e\u767b\u5f55\u56de\u8c03\u548c\u767b\u51fa\u56de\u8c03\uff0c\u914d\u7f6e\u4e3a\u4f60\u5b9e\u9645\u9879\u76ee\u7684\u5730\u5740\uff0c\u6211\u4eec\u5728\u8fd9\u91cc\u914d\u7f6e localhost \u7528\u4e8e\u6d4b\u8bd5\u3002

\n

\u82e5\u4f60\u60f3\u5339\u914d\u591a\u4e2a\u767b\u5f55 /\u767b\u51fa\u56de\u8c03\uff0c\u53ef\u4ee5\u4f7f\u7528 \u2018*\u2019 \u53f7\u8fdb\u884c\u901a\u914d\uff0c\u767b\u5f55 /\u767b\u51fa\u56de\u8c03\u53ef\u4ee5\u662f\u5982\u4e0b\u683c\u5f0f\uff1a

\n

\"\"

\n

\"\"

\n

\u5728\u534f\u8bae\u914d\u7f6e\u4e2d\uff0c\u6211\u4eec\u52fe\u9009 authorization_code \u5e76\u4e14\u4f7f\u7528 code \u4f5c\u4e3a\u8fd4\u56de\u7c7b\u578b\uff0c\u5982\u4e0b\u56fe\u6240\u793a\uff1a

\n

\"\"

\n

1.3 \u63a5\u5165\u6d4b\u8bd5

\n\n
GET${host}/oidc/auth \u53d1\u8d77\u767b\u5f55\uff08\u62fc\u63a5\u4f60\u7684\u53d1\u8d77\u767b\u5f55\u5730\u5740\uff09\nPOST${host}/oidc/token \u83b7\u53d6 Token\nGET${host}/session/me \u83b7\u53d6\u7528\u6237\u4fe1\u606f\nPOST${host}/oidc/token/introspection \u6821\u9a8c Token\nPOST${host}/oidc/token \u5237\u65b0 Token\nPOST${host}/oidc/revocation \u540a\u9500 Token\nGET${host}/session/end \u767b\u51fa\n
\n\n

\u4ee5\u4e0b\u8981\u4ecb\u7ecd\u7684\u63a5\u53e3\u53ef\u4ee5\u901a\u8fc7\u6211\u4eec\u7684\u5728\u7ebf postman collection \u81ea\u884c fork \u4f53\u9a8c\u3002

\n

\"\"

\n\n
GET${host}/oidc/auth\n
\n

\u8fd9\u662f\u57fa\u4e8e\u6d4f\u89c8\u5668\u7684 OIDC \u7684\u8d77\u70b9\uff0c\u8bf7\u6c42\u5bf9\u7528\u6237\u8fdb\u884c\u8eab\u4efd\u9a8c\u8bc1\uff0c\u5e76\u4f1a\u5728\u9a8c\u8bc1\u6210\u529f\u540e\u8fd4\u56de\u6388\u6743\u7801\u5230\u60a8\u6240\u6307\u5b9a\u7684 redirect_uri \u3002

\n

\u62fc\u63a5\u53d1\u8d77\u767b\u5f55\u5730\u5740\uff08\u6d4f\u89c8\u5668\u4e2d\u6253\u5f00\uff09\uff1a\nhttps://{host}/oidc/auth?scope=openid+profile+email+phone+username&redirect_uri={redirect_uri}&response_type=code&client_id={\u5e94\u7528 ID}&state={state}

\n

\u5982\u60a8\u9700\u8981\u989d\u5916\u83b7\u53d6 refresh_token \u5219\u8bf7\u6c42\u683c\u5f0f\u4e3a\uff1a\nhttps://{host}/oidc/auth?\nscope=openid+profile+offline_access+username+email+phone&redirect_uri=http://localhost:8080/&response_type=code&client_id={\u5e94\u7528 ID}&prompt=consent&state={state}

\n

\u70b9\u6b64\u4f53\u9a8c\uff1a\nhttps://oidc-authorization-code.authing.cn/oidc/auth?scope=openid+profile+offline_access+username+email+phone&redirect_uri=http://localhost:8080/&response_type=code&prompt=consent&nOnce=054d3c0e-9df9-46f2-a8fa-a7f479032660&client_id=63eb4585156d977101dd3750&state=1676366724

\n

\u53c2\u6570\u8bf4\u660e\uff1a

\n

\"\"

\n\n
POST${host}/oidc/token\n
\n

\u7528\u6237\u5728 Authing \u4fa7\u5b8c\u6210\u767b\u5f55\u64cd\u4f5c\u540e\uff0cAuthing \u4f1a\u5c06\u751f\u6210\u7684 code \u4f5c\u4e3a\u53c2\u6570\u56de\u8c03\u5230 redirect_uri \u5730\u5740\uff0c\u6b64\u65f6\u901a\u8fc7 code \u6362 token \u63a5\u53e3\u5373\u53ef\u62ff\u5230\u5bf9\u5e94\u7684\u8bbf\u95ee\u4ee4\u724c access_token \u3002

\n

\u8bf7\u6c42\u53c2\u6570\n\"\"

\n

\u8bf7\u6c42\u4e8b\u4f8b

\n
curl --location --request POST 'https://{host}/oidc/token' \\\n--header 'Content-Type: application/x-www-form-urlencoded' \\\n--data-urlencode 'client_id={\u5e94\u7528 ID}' \\\n--data-urlencode 'client_secret={\u5e94\u7528\u5bc6\u94a5}' \\\n--data-urlencode 'grant_type=authorization_code' \\\n--data-urlencode 'redirect_uri={\u53d1\u8d77\u767b\u5f55\u65f6\u6307\u5b9a\u7684 redirect_uri}' \\\n--data-urlencode 'code={/oidc/auth \u8fd4\u56de\u7684 code}'\n
\n

\u54cd\u5e94\u793a\u4f8b (\u6210\u529f)

\n
{\n \"scope\": \"openid username email phone offline_access profile\",\n \"token_type\": \"Bearer\",\n \"access_token\": \"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6ImVtSzBGbVRIa0xlQWFjeS1YWEpVT3J6SzkxV243TkdoNGFlYUVlSjVQOUUifQ.eyJzdWIiOiI2M2ViNTNjNDQxYTVjMmYwNWYyNGJiMDMiLCJhdWQiOiI2M2ViNDU4NTE1NmQ5NzcxMDFkZDM3NTAiLCJzY29wZSI6Im9wZW5pZCB1c2VybmFtZSBlbWFpbCBwaG9uZSBvZmZsaW5lX2FjY2VzcyBwcm9maWxlIiwiaWF0IjoxNjc2MzY2OTE0LCJleHAiOjE2Nzc1NzY1MTQsImp0aSI6ImVmVU04enNrbl92LXYzeXZfbDVHRV9fQ2JEY0NNZDhEVDFnYVI0bHRqcHAiLCJpc3MiOiJodHRwczovL29pZGMtYXV0aG9yaXphdGlvbi1jb2RlLmF1dGhpbmcuY24vb2lkYyJ9.E3gAYzCQbJmrtM5zl91OPHm2YPnDxzRejw75oVMF1tLqCS0trj6CSBxyxP3Z9t6Eb_oAu1f_3I6XC3KC-l0DTM6q7_R2rnW4LWlik2rDCLuGpG0FqFScLZhwafmrPsVn93yaBQfEEoaLviqKhj3DgOymKqHZzFG3taaz2k_pWsxt4z97DtKjRTiqyMvcSfHsVrjSKELaC-5S_PHPWcQ70iX85IwUb6i5ldZGxYmODCvChNC9p4D4IOT3atvyEHgBTmjA9ZKI-T7hCVHSO91WZY3l1p4iWdi6KdP1oMGTy8WbmUHG9SiWO1Efh_9I5ZpRzVNWXINLv-lZ0d2aZKjg2w\",\n \"expires_in\": 1209600,\n \"id_token\": \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiI2M2ViNTNjNDQxYTVjMmYwNWYyNGJiMDMiLCJhdWQiOiI2M2ViNDU4NTE1NmQ5NzcxMDFkZDM3NTAiLCJpYXQiOjE2NzYzNjY5MTQsImV4cCI6MTY3NzU3NjUxNCwiaXNzIjoiaHR0cHM6Ly9vaWRjLWF1dGhvcml6YXRpb24tY29kZS5hdXRoaW5nLmNuL29pZGMiLCJub25jZSI6IjhiYjg3MjdhLWU1MGUtNDUzOC05ZmZmLWZhOTFlNWQ0Y2MwYSIsIm5hbWUiOm51bGwsImdpdmVuX25hbWUiOm51bGwsIm1pZGRsZV9uYW1lIjpudWxsLCJmYW1pbHlfbmFtZSI6bnVsbCwibmlja25hbWUiOm51bGwsInByZWZlcnJlZF91c2VybmFtZSI6bnVsbCwicHJvZmlsZSI6bnVsbCwicGljdHVyZSI6Imh0dHBzOi8vZmlsZXMuYXV0aGluZy5jby9hdXRoaW5nLWNvbnNvbGUvZGVmYXVsdC11c2VyLWF2YXRhci5wbmciLCJ3ZWJzaXRlIjpudWxsLCJiaXJ0aGRhdGUiOm51bGwsImdlbmRlciI6IlUiLCJ6b25laW5mbyI6bnVsbCwibG9jYWxlIjpudWxsLCJ1cGRhdGVkX2F0IjoiMjAyMy0wMi0xNFQwOToyNjoyOC4wNjhaIiwiZW1haWwiOm51bGwsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwicGhvbmVfbnVtYmVyIjoiMTg1MTY4Mjk5OTUiLCJwaG9uZV9udW1iZXJfdmVyaWZpZWQiOnRydWUsInVzZXJuYW1lIjpudWxsfQ.GweoWBCEyHQGP6G9ohbfBMUMALlbZMM9hRAes1De7BM\",\n \"refresh_token\": \"KanvCEmonS_FgCRdFftOCwka2f8Qjj4tcsIfJF-VC1W\"\n}\n
\n

\u54cd\u5e94\u793a\u4f8b (\u5931\u8d25)

\n
{\n \"error\": \"invalid_grant\",\n \"error_description\": \"\u6388\u6743\u7801\u65e0\u6548\u6216\u5df2\u8fc7\u671f\"\n}\n
\n\n
GET${host}/session/me \u83b7\u53d6\u7528\u6237\u4fe1\u606f\n
\n

\u6b64\u7aef\u70b9\u662f OIDC \u83b7\u53d6\u7528\u6237\u7aef\u70b9\uff0c\u53ef\u4ee5\u901a\u8fc7 AccessToken \u83b7\u53d6\u6709\u5173\u5f53\u524d\u767b\u5f55\u7528\u6237\u7684\u4fe1\u606f\u3002

\n

\u8bf7\u6c42\u53c2\u6570\n\"\"

\n

\u8bf7\u6c42\u793a\u4f8b

\n
curl --location --request GET 'https://{host}/oidc/me?access_token={access_token}' \n
\n

\u54cd\u5e94\u793a\u4f8b (\u6210\u529f)

\n
{\n \"name\": null,\n \"given_name\": null,\n \"middle_name\": null,\n \"family_name\": null,\n \"nickname\": null,\n \"preferred_username\": null,\n \"profile\": null,\n \"picture\": \"https://files.authing.co/authing-console/default-user-avatar.png\",\n \"website\": null,\n \"birthdate\": null,\n \"gender\": \"U\",\n \"zoneinfo\": null,\n \"locale\": null,\n \"updated_at\": \"2023-02-14T09:26:28.068Z\",\n \"email\": \"xxx@authing.cn\",\n \"email_verified\": true,\n \"phone_number\": \"185xxxx9995\",\n \"phone_number_verified\": true,\n \"username\": \"neo\",\n \"sub\": \"63eb53c441a5c2f05f24bb03\"\n}\n
\n

\u54cd\u5e94\u793a\u4f8b (\u5931\u8d25)

\n
{\n \"error\": \"invalid_grant\",\n \"error_description\": \"Access Token \u65e0\u6548\"\n}\n
\n\n
POST${host}/oidc/token/introspection\n
\n

\u6b64\u7aef\u70b9\u63a5\u53d7 access_token \u3001id_token \u3001refresh_token \uff0c\u5e76\u8fd4\u56de\u4e00\u4e2a\u5e03\u5c14\u503c\uff0c\u6307\u793a\u5b83\u662f\u5426\u5904\u4e8e\u6d3b\u52a8\u72b6\u6001\u3002\u5982\u679c\u4ee4\u724c\u5904\u4e8e\u6d3b\u52a8\u72b6\u6001\uff0c\u8fd8\u5c06\u8fd4\u56de\u6709\u5173\u4ee4\u724c\u7684\u5176\u4ed6\u6570\u636e\u3002\u5982\u679c token \u65e0\u6548\u3001\u8fc7\u671f\u6216\u88ab\u540a\u9500\uff0c\u5219\u8ba4\u4e3a\u5b83\u5904\u4e8e\u975e\u6d3b\u52a8\u72b6\u6001\u3002

\n

1.\u9a8c\u8bc1 Token \u5206\u4e3a\u4e24\u79cd\u65b9\u5f0f\uff1a

\n

\u672c\u5730\u9a8c\u8bc1\u4e0e\u4f7f\u7528 Authing \u5728\u7ebf\u9a8c\u8bc1\u3002\u6211\u4eec\u5efa\u8bae\u5728\u672c\u5730\u9a8c\u8bc1 JWT Token \uff0c\u56e0\u4e3a\u53ef\u4ee5\u8282\u7701\u4f60\u7684\u670d\u52a1\u5668\u5e26\u5bbd\u5e76\u52a0\u5feb\u9a8c\u8bc1\u901f\u5ea6\u3002\u4f60\u4e5f\u53ef\u4ee5\u9009\u62e9\u5c06 Token \u53d1\u9001\u5230 Authing \u7684\u9a8c\u8bc1\u63a5\u53e3\u7531 Authing \u8fdb\u884c\u9a8c\u8bc1\u5e76\u8fd4\u56de\u7ed3\u679c\uff0c\u4f46\u8fd9\u6837\u4f1a\u9020\u6210\u7f51\u7edc\u5ef6\u8fdf\uff0c\u800c\u4e14\u5728\u7f51\u7edc\u62e5\u585e\u65f6\u53ef\u80fd\u4f1a\u6709\u6162\u901f\u8bf7\u6c42\u3002

\n

access_token \u53ef\u4ee5\u4f7f\u7528 RS256 \u7b7e\u540d\u7b97\u6cd5\u6216 HS256 \u7b7e\u540d\u7b97\u6cd5\u8fdb\u884c\u7b7e\u540d\u3002\u4e0b\u9762\u662f\u8fd9\u4e24\u79cd\u7b7e\u540d\u7b97\u6cd5\u7684\u533a\u522b\uff1a

\n

RS256 \u662f\u4f7f\u7528 RSA \u7b97\u6cd5\u7684\u4e00\u79cd\u6570\u5b57\u7b7e\u540d\u7b97\u6cd5\uff0c\u5b83\u4f7f\u7528\u516c\u94a5 /\u79c1\u94a5\u5bf9\u6765\u52a0\u5bc6\u548c\u9a8c\u8bc1\u4fe1\u606f\u3002RS256 \u7b7e\u540d\u751f\u6210\u7684\u4ee4\u724c\u6bd4 HS256 \u7b7e\u540d\u751f\u6210\u7684\u4ee4\u724c\u66f4\u52a0\u5b89\u5168\uff0c\u56e0\u4e3a\u4f7f\u7528 RSA \u5bc6\u94a5\u5bf9\u8fdb\u884c\u7b7e\u540d\u53ef\u4ee5\u63d0\u4f9b\u66f4\u9ad8\u7684\u4fdd\u62a4\u7ea7\u522b\u3002\u4f7f\u7528 RS256 \u7b7e\u540d\u7b97\u6cd5\u7684\u4ee4\u724c\u53ef\u4ee5\u4f7f\u7528\u516c\u94a5\u8fdb\u884c\u9a8c\u8bc1\uff0c\u516c\u94a5\u53ef\u4ee5\u901a\u8fc7 JWK \u7aef\u70b9\u83b7\u53d6\u3002

\n

HS256 \u662f\u4f7f\u7528\u5bf9\u79f0\u5bc6\u94a5\u7684\u4e00\u79cd\u6570\u5b57\u7b7e\u540d\u7b97\u6cd5\u3002\u5b83\u4f7f\u7528\u540c\u4e00\u4e2a\u5bc6\u94a5\u8fdb\u884c\u7b7e\u540d\u548c\u9a8c\u8bc1\u3002HS256 \u7b7e\u540d\u7b97\u6cd5\u5728\u6027\u80fd\u65b9\u9762\u6bd4 RS256 \u7b7e\u540d\u7b97\u6cd5\u66f4\u5feb\uff0c\u56e0\u4e3a\u5b83\u4f7f\u7528\u7684\u662f\u5bf9\u79f0\u5bc6\u94a5\uff0c\u800c\u4e0d\u662f\u4f7f\u7528 RSA \u516c\u94a5 /\u79c1\u94a5\u5bf9\u6765\u7b7e\u540d\u548c\u9a8c\u8bc1\u3002\u4f7f\u7528 HS256 \u7b7e\u540d\u7b97\u6cd5\u7684\u4ee4\u724c\u53ef\u4ee5\u901a\u8fc7 shared secret \uff08\u5e94\u7528\u5bc6\u94a5\uff09\u8fdb\u884c\u9a8c\u8bc1\u3002\n\u5728\u5b9e\u9645\u5e94\u7528\u4e2d\uff0cRS256 \u7b97\u6cd5\u66f4\u52a0\u5b89\u5168\uff0c\u4f46\u540c\u65f6\u4e5f\u66f4\u52a0\u6d88\u8017\u8d44\u6e90\uff0c\u5982\u679c\u7cfb\u7edf\u9700\u8981\u9ad8\u6027\u80fd\uff0c\u53ef\u4ee5\u9009\u62e9 HS256 \u7b7e\u540d\u7b97\u6cd5\u3002

\n

\u4ee5\u4e0b\u662f\u672c\u5730\u9a8c\u8bc1\u548c\u5728\u7ebf\u9a8c\u8bc1\u7684\u4f18\u52a3\u5bf9\u6bd4\uff1a

\n

\"\"

\n

2.\u5728\u7ebf\u9a8c\u8bc1

\n

\u9700\u8981\u6ce8\u610f\u7684\u662f\uff0cid_token \u76ee\u524d\u65e0\u6cd5\u5728\u7ebf\u6821\u9a8c\uff0c\u56e0\u4e3a id_token \u53ea\u662f\u4e00\u4e2a\u6807\u8bc6\uff0c\u82e5\u9700\u8981\u6821\u9a8c id_token \u5219\u9700\u8981\u60a8\u5728\u79bb\u7ebf\u81ea\u884c\u6821\u9a8c\u3002

\n

\u8bf7\u6c42\u53c2\u6570

\n

\"\"

\n

\u8bf7\u6c42\u793a\u4f8b

\n
curl --location --request POST 'https://{host}/oidc/token/introspection' \\\n--header 'Content-Type: application/x-www-form-urlencoded' \\\n--data-urlencode 'client_id={\u5e94\u7528 ID}' \\\n--data-urlencode 'client_secret={\u5e94\u7528\u5bc6\u94a5}' \\\n--data-urlencode 'token={ token }' \\\n--data-urlencode 'token_type_hint={token_type_hint}'\n
\n

\u6821\u9a8c access_token \u54cd\u5e94\u793a\u4f8b\uff08\u6821\u9a8c\u901a\u8fc7\uff09

\n
{\n \"active\": true,\n \"sub\": \"63eb53c441a5c2f05f24bb03\",\n \"client_id\": \"63eb4585156d977101dd3750\",\n \"exp\": 1677648467,\n \"iat\": 1676438867,\n \"iss\": \"https://oidc-authorization-code.authing.cn/oidc\",\n \"jti\": \"ObgavGBUocr1wsrUvtDLHmuFSgoebxsiOY4JNRqIhaQ\",\n \"scope\": \"offline_access username profile openid phone email\",\n \"token_type\": \"Bearer\"\n}\n
\n

\u6821\u9a8c access_token \u54cd\u5e94\u793a\u4f8b\uff08\u6821\u9a8c\u672a\u901a\u8fc7\uff09

\n
{\n \"active\": false\n}\n
\n

\u6821\u9a8c refresh_token \u54cd\u5e94\u793a\u4f8b (\u6821\u9a8c\u901a\u8fc7)

\n
{\n \"active\": true,\n \"sub\": \"63eb53c441a5c2f05f24bb03\",\n \"client_id\": \"63eb4585156d977101dd3750\",\n \"exp\": 1679030867,\n \"iat\": 1676438867,\n \"iss\": \"https://oidc-authorization-code.authing.cn/oidc\",\n \"jti\": \"6F2TO1v1YZ1_N7I3jXYHjK-vZzKtlD0IiP5KPoUFUCQ\",\n \"scope\": \"offline_access username profile openid phone email\"\n}\n
\n

\u6821\u9a8c refresh_token \u54cd\u5e94\u793a\u4f8b\uff08\u6821\u9a8c\u672a\u901a\u8fc7\uff09

\n
{\n \"active\": false\n}\n
\n

3.\u79bb\u7ebf\u6821\u9a8c

\n

\u53ef\u53c2\u8003\u6587\u6863\uff1a\u79bb\u7ebf\u6821\u9a8c\uff08 \u6587\u6863\u94fe\u63a5\uff1a https://docs.authing.cn/v2/guides/faqs/how-to-validate-user-token.html# \uff09

\n

\u6211\u4eec\u7b80\u5355\u8bf4\u4e0b\uff0c\u82e5\u60a8\u4f7f\u7528\u79bb\u7ebf\u6821\u9a8c\u5e94\u8be5\u5bf9 token \u8fdb\u884c\u5982\u4e0b\u89c4\u5219\u7684\u6821\u9a8c\uff1a

\n

1.\u683c\u5f0f\u6821\u9a8c - \u6821\u9a8c token \u683c\u5f0f\u662f\u5426\u662f JWT \u683c\u5f0f\n2.\u7c7b\u578b\u6821\u9a8c - \u6821\u9a8c token \u662f\u5426\u662f\u76ee\u6807 token \u7c7b\u578b\uff0c\u6bd4\u5982 access_token \u3001id_token \u3001refresh_token\n3.issuer \u6821\u9a8c - \u6821\u9a8c token \u662f\u5426\u4e3a\u4fe1\u8d56\u7684 issuer \u9881\u53d1\n4.\u7b7e\u540d\u6821\u9a8c - \u6821\u9a8c token \u7b7e\u540d\u662f\u5426\u7531 issuer \u7b7e\u53d1\uff0c\u9632\u6b62\u4f2a\u9020\n5.\u65f6\u95f4\u6821\u9a8c - \u6821\u9a8c token \u662f\u5426\u5728\u6709\u6548\u671f\u5185\n6.claims \u6821\u9a8c - \u662f\u5426\u7b26\u5408\u4e0e\u9884\u671f\u7684\u4e00\u81f4

\n

\u4ee5\u4e0a 6 \u70b9\u5747\u6821\u9a8c\u901a\u8fc7\uff0c\u6211\u4eec\u624d\u80fd\u8ba4\u4e3a token \u662f\u6709\u6548\u4e14\u5408\u6cd5\u7684\u3002

\n

\u4e0b\u9762\u662f\u4e00\u4e2a\u793a\u4f8b Java \u4ee3\u7801\uff0c\u53ef\u4ee5\u7528\u4e8e\u5728\u672c\u5730\u6821\u9a8c OIDC RS256 \u548c HS256 \u7b7e\u53d1\u7684 access_token \u3002

\n
import com.nimbusds.jose.JWSObject;\nimport com.nimbusds.jwt.JWTClaimsSet;\nimport com.nimbusds.jwt.SignedJWT;\n\nimport java.net.URL;\nimport java.text.ParseException;\nimport java.util.Date;\n\npublic class OIDCValidator {\n private static final String ISSUER = \"https://your-issuer.com\";\n private static final String AUDIENCE = \"your-client-id\";\n\n private final URL jwkUrl;\n\n public OIDCValidator(final URL jwkUrl) {\n this.jwkUrl = jwkUrl;\n }\n\n public JWTClaimsSet validateToken(final String accessToken) throws ParseException {\n final SignedJWT signedJWT = SignedJWT.parse(accessToken);\n if (signedJWT == null) {\n throw new RuntimeException(\"Access token is null or empty\");\n }\n\n final JWTClaimsSet claims = signedJWT.getJWTClaimsSet();\n if (claims == null) {\n throw new RuntimeException(\"No claims present in the access token\");\n }\n\n if (!claims.getIssuer().equals(ISSUER)) {\n throw new RuntimeException(\"Invalid issuer in access token\");\n }\n\n if (!claims.getAudience().contains(AUDIENCE)) {\n throw new RuntimeException(\"Invalid audience in access token\");\n }\n\n final JWSObject jwsObject = signedJWT.getJWSObject();\n if (jwsObject == null) {\n throw new RuntimeException(\"No JWS object found in the access token\");\n }\n\n // Fetch the JWKs from the JWK set URL\n final JWKSet jwkSet = JWKSet.load(jwkUrl);\n final JWK jwk = jwkSet.getKeyByKeyId(jwsObject.getHeader().getKeyID());\n if (jwk == null) {\n throw new RuntimeException(\"No JWK found for the access token\");\n }\n\n if (!jwsObject.verify(jwk.getKey())) {\n throw new RuntimeException(\"Invalid signature in access token\");\n }\n\n if (claims.getExpirationTime() == null || claims.getExpirationTime().before(new Date())) {\n throw new RuntimeException(\"Expired access token\");\n }\n\n return claims;\n }\n}\n
\n

\u8fd9\u6bb5\u4ee3\u7801\u4f7f\u7528 Nimbus JOSE+JWT \u5e93\u6765\u89e3\u6790\u548c\u9a8c\u8bc1 JWT token \u3002\u5b83\u4f7f\u7528\u6307\u5b9a\u7684 issuer \u548c audience \u503c\u5bf9 access_token \u8fdb\u884c\u9a8c\u8bc1\uff0c\u5e76\u9a8c\u8bc1 JWT \u4e2d claims \u7684\u683c\u5f0f\u3001\u7c7b\u578b\u3001\u7b7e\u540d\u3001\u6709\u6548\u671f\u548c issuer \u3002\u5982\u679c\u53d1\u751f\u4efb\u4f55\u9a8c\u8bc1\u9519\u8bef\uff0c\u5219\u5c06\u629b\u51fa RuntimeException \u3002\u4f7f\u7528\u65f6\u9700\u8981\u4f20\u5165\u5bf9\u5e94\u7684 JWK URL \u548c access_token \u8fdb\u884c\u8c03\u7528\uff0c\u4f8b\u5982\uff1a

\n
final URL jwkUrl = new URL(\"https://your-issuer.com/.well-known/jwks.json\");\nfinal OIDCValidator validator = new OIDCValidator(jwkUrl);\nfinal String accessToken = \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJleHAiOjE1MTYyMzkwMjJ9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c\";\nfinal JWTClaimsSet claims = validator.validateToken(accessToken);\n
\n

\u8fd9\u4e2a\u793a\u4f8b\u53ea\u6821\u9a8c\u4e86 RS256 \u548c HS256 \u7b7e\u540d\u7b97\u6cd5\u3002

\n\n
POST${host}/oidc/token\n
\n

\u6b64\u529f\u80fd\u7528\u4e8e\u7528\u6237 token \u7684\u5237\u65b0\u64cd\u4f5c\uff0c\u5728 token \u83b7\u53d6\u9636\u6bb5\u9700\u8981\u5148\u83b7\u53d6\u5230 refresh_token \u3002

\n

\u8bf7\u6c42\u53c2\u6570\n\"\"

\n

\u8bf7\u6c42\u793a\u4f8b

\n
curl --location --request POST 'https://{host}/oidc/token' \\\n--header 'Content-Type: application/x-www-form-urlencoded' \\\n--data-urlencode 'client_id={\u5e94\u7528 ID}' \\\n--data-urlencode 'client_secret={\u5e94\u7528\u5bc6\u94a5}' \\\n--data-urlencode 'refresh_token={\u5237\u65b0\u4ee4\u724c}' \\\n--data-urlencode 'grant_type=refresh_token'\n
\n

\u54cd\u5e94\u793a\u4f8b(\u6210\u529f)

\n
{\n \"refresh_token\": \"6F2TO1v1YZ1_N7I3jXYHjK-vZzKtlD0IiP5KPoUFUCQ\",\n \"scope\": \"offline_access username profile openid phone email\",\n \"token_type\": \"Bearer\",\n \"access_token\": \"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6ImVtSzBGbVRIa0xlQWFjeS1YWEpVT3J6SzkxV243TkdoNGFlYUVlSjVQOUUifQ.eyJzdWIiOiI2M2ViNTNjNDQxYTVjMmYwNWYyNGJiMDMiLCJhdWQiOiI2M2ViNDU4NTE1NmQ5NzcxMDFkZDM3NTAiLCJzY29wZSI6Im9mZmxpbmVfYWNjZXNzIHVzZXJuYW1lIHByb2ZpbGUgb3BlbmlkIHBob25lIGVtYWlsIiwiaWF0IjoxNjc2NDQ0MjY4LCJleHAiOjE2Nzc2NTM4NjgsImp0aSI6IkEtZUlQYkJ5N3lJLTliUmp1RnJHeXNCSXdjbWtOUl9WalpYODB2aU05VFkiLCJpc3MiOiJodHRwczovL29pZGMtYXV0aG9yaXphdGlvbi1jb2RlLmF1dGhpbmcuY24vb2lkYyJ9.Kk3jSK5BSUEDVTQMdMAdG5cBCxZt31vQiD-XYHNA84Gd3Mo8eDLcQpjMEzQ8HJ4_b9IgMOz5ydXz0zAQ6AjLMW3Rl49qhTGDB7Kq7tHTFmDO8itoO2LQTCLPCPtP3TkoOgptlFD_sd32nefH-HojNhuqwKw469Byw3xnW5xEs3wSuOoUdHwR2n9j1T1Zgp3e90xmBjbtbofQE1z0IWtCnrfJ9ujWsKXoN_7OAXbCTa-Ak_DhgLHU7xutQaaBOgD28lLLT5xclgBWfv7Leyx_kBnVGT5Jvo1tfA6AUEp6wJO4GUBzsijLefI04VDzBGypNuFJlw_jOhSp-SWxJjQSwQ\",\n \"expires_in\": 1209600,\n \"id_token\": \"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiI2M2ViNTNjNDQxYTVjMmYwNWYyNGJiMDMiLCJhdWQiOiI2M2ViNDU4NTE1NmQ5NzcxMDFkZDM3NTAiLCJpYXQiOjE2NzY0NDQyNjgsImV4cCI6MTY3NzY1Mzg2OCwiaXNzIjoiaHR0cHM6Ly9vaWRjLWF1dGhvcml6YXRpb24tY29kZS5hdXRoaW5nLmNuL29pZGMiLCJuYW1lIjpudWxsLCJnaXZlbl9uYW1lIjpudWxsLCJtaWRkbGVfbmFtZSI6bnVsbCwiZmFtaWx5X25hbWUiOm51bGwsIm5pY2tuYW1lIjpudWxsLCJwcmVmZXJyZWRfdXNlcm5hbWUiOm51bGwsInByb2ZpbGUiOm51bGwsInBpY3R1cmUiOiJodHRwczovL2ZpbGVzLmF1dGhpbmcuY28vYXV0aGluZy1jb25zb2xlL2RlZmF1bHQtdXNlci1hdmF0YXIucG5nIiwid2Vic2l0ZSI6bnVsbCwiYmlydGhkYXRlIjpudWxsLCJnZW5kZXIiOiJVIiwiem9uZWluZm8iOm51bGwsImxvY2FsZSI6bnVsbCwidXBkYXRlZF9hdCI6IjIwMjMtMDItMTRUMDk6MjY6MjguMDY4WiIsImVtYWlsIjpudWxsLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsInBob25lX251bWJlciI6IjE4NTE2ODI5OTk1IiwicGhvbmVfbnVtYmVyX3ZlcmlmaWVkIjp0cnVlLCJ1c2VybmFtZSI6bnVsbH0.DGoJrzkgti44zw-MotVM1KpLxbJTzc5pfh-xYun_xDQ\"\n}\n
\n

\u54cd\u5e94\u793a\u4f8b\uff08\u5931\u8d25\uff09

\n
{\n \"error\": \"invalid_grant\",\n \"error_description\": \"Refresh Token \u65e0\u6548\u6216\u5df2\u8fc7\u671f\"\n}\n
\n\n
POST${host}/oidc/token/revocation\n
\n

\u64a4\u9500 access_token / refresh_token

\n

\u8bf7\u6c42\u53c2\u6570

\n

\"\"

\n

\u8bf7\u6c42\u793a\u4f8b

\n
curl --location --request POST 'https://{host}/oidc/token/revocation' \\\n--header 'Content-Type: application/x-www-form-urlencoded' \\\n--data-urlencode 'client_id={\u5e94\u7528 ID}' \\\n--data-urlencode 'client_secret={\u5e94\u7528\u5bc6\u94a5}' \\\n--data-urlencode 'token= {token}' \\\n--data-urlencode 'token_type_hint={token_type_hint}'\n
\n

\u54cd\u5e94\u793a\u4f8b\uff08\u6210\u529f\uff09

\n
HTTP 200 OK\n
\n

\u54cd\u5e94\u793a\u4f8b\uff08\u5931\u8d25\uff09

\n
{\n \"error\": \"xxxx\",\n \"error_description\": \"xxxx\"\n}\n
\n\n
GET${host}/oidc/session/end\n
\n

\u4f7f\u7528\u6b64\u64cd\u4f5c\u901a\u8fc7\u5220\u9664\u7528\u6237\u7684\u6d4f\u89c8\u5668\u4f1a\u8bdd\u6765\u6ce8\u9500\u7528\u6237\u3002\npost_logout_redirect_uri \u53ef\u4ee5\u6307\u5b9a\u5728\u6267\u884c\u6ce8\u9500\u540e\u91cd\u5b9a\u5411\u7684\u5730\u5740\u3002\u5426\u5219\uff0c\u6d4f\u89c8\u5668\u5c06\u91cd\u5b9a\u5411\u5230\u9ed8\u8ba4\u9875\u9762

\n

\u8bf7\u6c42\u53c2\u6570

\n

\"\"

\n

\u8bf7\u6c42\u793a\u4f8b (\u6d4f\u89c8\u5668\u8bbf\u95ee)

\n
GET https://oidc-authorization-code.authing.cn/oidc/session/end?id_token_hint={id_token}&post_logout_redirect_uri=http://localhost:8080/&state=1676452381\n
\n

02 SSO (Single Sign-On) \u5355\u70b9\u767b\u5f55 & SLO (Single Logout) \u5355\u70b9\u767b\u51fa

\n

2.1 SSO \u5b9e\u73b0

\n

SSO(Single Sign-On) \u5355\u70b9\u767b\u5f55\uff0c\u5373\u540c\u65f6\u8bbf\u95ee\u591a\u4e2a\u5e94\u7528\u4ec5\u9700\u8981\u767b\u5f55\u4e00\u6b21\u3002

\n

\u4e3e\u4f8b\uff1a\u6211\u4eec\u73b0\u5728\u6709\u4e24\u4e2a\u7ad9\u70b9\u5206\u522b\u662f\nuthing.com\nething.com\n\u6211\u4eec\u5e0c\u671b\u7528\u6237\u5728 uthing.com \u8fdb\u884c\u8ba4\u8bc1\u540e\uff0c\u8df3\u8f6c\u5230 ething \u540e\u65e0\u9700\u4e8c\u6b21\u8ba4\u8bc1\uff0c\u53cd\u4e4b\u4e5f\u662f\u4e00\u6837\u7684\u3002

\n

\u5177\u4f53\u6d41\u7a0b\uff1a

\n

1.\u7528\u6237\u8bbf\u95ee uthing.com \uff0cuthing \u524d\u7aef\u53d1\u73b0\u7528\u6237\u672a\u8ba4\u8bc1\uff0c\u8df3\u8f6c\u81f3 Authing \u8fdb\u884c\u8ba4\u8bc1\u3002

\n

2.\u7528\u6237\u5728 Authing \u53d1\u8d77\u8ba4\u8bc1\u5b8c\u6210\uff0cAuthing \u521b\u5efa SSO Session \uff0c\u4e0b\u53d1\u4e34\u65f6\u6388\u6743\u7801 (code) \u91cd\u5b9a\u5411\u5230 uthing \u540e\u53f0\u3002

\n

\u9700\u8981\u6ce8\u610f\u7684\u662f\uff0c\u5728\u8fd9\u91cc\u6211\u4eec\u4e5f\u53ef\u4ee5\u91cd\u5b9a\u5411\u5230\u524d\u7aef\u9875\u9762\uff0c\u518d\u7531\u524d\u7aef\u9875\u9762\u81ea\u884c\u5224\u65ad\u5982\u679c\u662f Authing \u56de\u8c03\u8bf7\u6c42\uff0c\u5219\u643a\u5e26\u4e34\u65f6 code \u5230 uthing \u540e\u53f0\u53bb\u83b7\u53d6 token \u3002

\n

3.uthing \u540e\u53f0\u901a\u8fc7 code \u5411 Authing \u6362\u53d6 access_token \u3001id_token \u3001refresh_token \u7b49\uff0c\u5e76\u4e0b\u53d1\u7ed9\u524d\u7aef\u3002

\n

4.uthing \u524d\u7aef\u901a\u8fc7 access_token \u53ef\u4ee5\u76f4\u63a5\u5411 Authing OIDC \u7528\u6237\u4fe1\u606f\u7aef\u70b9\u83b7\u53d6\u5f53\u524d\u7528\u6237\u4fe1\u606f\u3002

\n

5.uthing \u524d\u7aef\u5728\u5728\u540e\u7eed\u8bf7\u6c42\u540e\u53f0\u65f6\uff0c\u643a\u5e26\u7531 Authing \u9881\u53d1\u7684 access_token \uff0c\u540e\u53f0\u5728\u63a5\u53d7\u5230\u7528\u6237\u8bf7\u6c42\u540e\u53bb Authing \u6821\u9a8c Token \u662f\u5426\u6709\u6548\uff0c\u6709\u6548\u5219\u53ef\u653e\u884c\uff0c\u82e5 Token \u6821\u9a8c\u5931\u8d25\u6216\u5df2\u8fc7\u671f\u5219\u8fd4\u56de\u9519\u8bef\u4fe1\u606f\u3002

\n

6.\u7528\u6237\u8bbf\u95ee ething.com \uff0cething \u8df3\u8f6c\u81f3 Authing \u8fdb\u884c\u8ba4\u8bc1\u3002

\n

7.\u7531\u4e8e\u7528\u6237\u5728 Authing \u5df2\u7ecf\u5b8c\u6210\u8ba4\u8bc1\uff0c\u521b\u5efa\u4e86 sso_session \uff0cAuthing \u4fa7\u76f4\u63a5\u4e0b\u53d1\u4e34\u65f6\u6388\u6743\u7801 (code) \uff0c\u65e0\u9700\u4e8c\u6b21\u8ba4\u8bc1\uff0c\u540e\u7eed\u6d41\u7a0b\u540c 1 \u3002

\n

\u6211\u4eec\u53d1\u73b0\uff0c\u7528\u6237\u5728 uthing \u8ba4\u8bc1\u6210\u529f\u7684\u65f6\u5019\uff0c\u518d\u8bbf\u95ee ething \u7684\u65f6\u5019\u4f1a\u5411 Authing \u8df3\u8f6c\u4e00\u4e0b\uff0c\u624d\u80fd\u5b8c\u6210\u540e\u7eed\u6d41\u7a0b\uff0c\u8fd9\u662f\u7531\u4e8e ething.com \u548c uthing.com \u5e76\u4e0d\u662f\u540c\u4e00\u4e2a\u7ad9\u70b9\uff0c\u65e0\u6cd5\u5b9e\u73b0 cookie \u5171\u4eab\uff0c\u5982\u679c\u4f60\u7684\u4ea7\u54c1\u5730\u5740\u662f \uff1a\nuthing.xxx.com\nething.xxx.com\n\u6211\u4eec\u5219\u53ef\u4ee5\u5229\u7528\u76f8\u540c\u57df\u4e0b cookie \u5171\u4eab\u7684\u65b9\u5f0f\u5b9e\u73b0 SSO \uff0c\u4ece\u800c\u907f\u514d\u6b64\u95ee\u9898\u3002

\n

\"\"

\n

2.2 SLO \u5b9e\u73b0

\n

SLO(Single Logout) \u5355\u70b9\u767b\u51fa\uff0c\u5373\u591a\u4e2a\u5e94\u7528\u4ec5\u9700\u8981\u767b\u51fa\u4e00\u6b21\uff0c\u5176\u4ed6\u5e94\u7528\u4e5f\u81ea\u52a8\u767b\u51fa \u3002

\n\n

\u5219 SLO \u6d41\u7a0b\u5982\u4e0b\uff1a

\n

1.\u7528\u6237\u5728\u67d0\u4e2a\u7ad9\u70b9\u767b\u51fa\uff0c\u6211\u4eec\u5219\u9700\u8981\u8c03\u7528 OIDC \u767b\u51fa\u7aef\u70b9\u9500\u6bc1 Token \uff0c\u7531\u4e8e\u662f cookie \u5171\u4eab\u5b9e\u73b0\u7684 SSO \uff0c\u7136\u540e\u6e05\u9664 xxx.com \u5bf9\u5e94\u4f1a\u8bdd\u7684 cookie \u5373\u53ef\u3002

\n

2.ething / uting \u5e94\u5f53\u5728\u6bcf\u6b21\u53d1\u8d77\u8bf7\u6c42\u524d\uff0c\u5224\u65ad cookie \u4e2d\u662f\u5426\u5b58\u5728\u767b\u5f55\u6001\uff0c\u82e5\u4e0d\u5b58\u5728\uff0c\u5219\u9700\u8981\u8df3\u8f6c\u9ed8\u8ba4\u9875\u9762\u63d0\u793a\u7528\u6237\u5df2\u7ecf\u767b\u51fa\u3002

\n\n

\u5982\u679c\u4f60\u7684\u4ea7\u54c1\u5730\u5740\u4e0d\u662f\u540c\u4e00\u4e2a\u57df\uff0c\u4f8b\u5982\uff1a\nuthing.com\nething.com

\n

\u5219 SLO \u6d41\u7a0b\u5982\u4e0b\uff1a

\n

1.\u7528\u6237\u5728\u67d0\u4e2a\u7ad9\u70b9\u767b\u51fa\uff0c\u6211\u4eec\u5219\u9700\u8981\u8c03\u7528 OIDC \u767b\u51fa\u7aef\u70b9\u9500\u6bc1 Token \uff0c\u5728 Authing \u7684\u5e94\u7528\u914d\u7f6e\u4e2d\uff0c\u4f60\u5e94\u5f53\u5148\u628a\u5e94\u7528\u90fd\u6dfb\u52a0\u5230 SSO \u4e2d\uff0c\u6216\u8005 uthing.com \u548c ething.com \u4f7f\u7528 Authing \u7684\u540c\u4e00\u4e2a\u81ea\u5efa\u5e94\u7528\uff0c\u5f53\u7528\u6237\u5728\u67d0\u4e2a\u7ad9\u70b9\u767b\u51fa\u540e\uff0c\u53e6\u5916\u4e00\u4e2a\u7ad9\u70b9\u7684 Token \u4e5f\u4f1a\u5931\u6548\u3002\n2.\u7528\u6237\u672a\u767b\u51fa\u7684\u7ad9\u70b9\u53d1\u8d77\u8bf7\u6c42\uff0c\u5f53\u540e\u53f0\u6821\u9a8c Token \u5931\u8d25\u540e\uff0c\u5219\u4e0b\u53d1\u6e05\u9664 cookie \u7684\u547d\u4ee4\u5e76\u8df3\u8f6c\u9ed8\u8ba4\u9875\u9762\u63d0\u793a\u7528\u6237\u5df2\u7ecf\u767b\u51fa\uff0c\u9700\u8981\u767b\u5f55\u3002

\n

03 \u672c\u7ae0\u603b\u7ed3

\n

\u672c\u7ae0\u6211\u4eec\u4ecb\u7ecd\u4e86 OIDC \u6388\u6743\u7801\u6a21\u5f0f\u7684\u63a5\u5165\u6d41\u7a0b\u4ee5\u53ca\u76f8\u5173\u63a5\u53e3\u7684\u8c03\u7528\u65b9\u5f0f\uff0c\u5bf9\u4e8e\u5c0f\u767d\u6765\u8bf4\u53ef\u80fd\u9700\u8981\u6574\u4f53\u8dd1\u4e00\u904d\u6d41\u7a0b\u624d\u80fd\u719f\u6089\uff0c\u6211\u4eec\u4e5f\u5efa\u8bae\u4f60 fork \u6211\u4eec\u7684 postman collection \u8dd1\u4e00\u904d\u6d41\u7a0b\uff0c\u5bf9\u6388\u6743\u7801\u6a21\u5f0f\u4f60\u5c31\u57fa\u672c\u638c\u63e1\u5566\u3002

\n

\u63a5\u4e0b\u6765\u6211\u4eec\u8fd8\u4f1a\u4ecb\u7ecd OIDC \u7684\u6388\u6743\u7801+PKCE \u6d41\u7a0b\uff0c\u4ee5\u53ca\u63a5\u5165 Authing \u7684\u65b9\u5f0f\uff0c\u9700\u8981\u4f60\u5bf9\u6388\u6743\u7801\u6a21\u5f0f\u7684\u6d41\u7a0b\u6709\u4e00\u5b9a\u4e86\u89e3\u54e6\u3002

\n" }, { "author": { "url": "member/hanbings", "name": "hanbings", "avatar": "https://cdn.v2ex.com/avatar/9d28/226c/519990_large.png?m=1685583692" }, "url": "t/907085", "date_modified": "2023-01-06T12:57:59+00:00", "content_html": "

\u76ee\u524d\u6b63\u5728\u9002\u914d\u5e38\u89c1\u7684\u56fd\u5916\u5e73\u53f0\uff0c\u8fdf\u4e00\u4e9b\u4f1a\u505a\u56fd\u5185\u7684\u50cf QQ \u5fae\u4fe1 WB \u767e\u5ea6 \u963f\u91cc \u4ec0\u4e48\u7684

\n

\u6b22\u8fce Star \u8ddf\u8fdb\uff01 Github\uff1aFluocean

\n

\"Fluocean\"

\n

\u4e3b\u8981\u7279\u6027\uff1a

\n\n

Github OAuth \u793a\u4f8b

\n

\u6d0b\u6d41\u63d0\u4f9b\u4e86\u8bb8\u591a\u7684\u91cd\u8f7d\u65b9\u6cd5\uff0c\u7528\u4e8e\u5e94\u5bf9\u4e0d\u540c\u60c5\u51b5\u4e0b\u7684\u8bf7\u6c42\uff0c\u6709\u4e9b\u5e26\u81ea\u6709\u8bf7\u6c42\u5934\u7684\uff0c\u4e5f\u6709\u8981\u6c42\u5fc5\u987b\u8981 Scope \u7684\u3002

\n
// \u521b\u5efa OAuth \u539f\u59cb\u5904\u7406\u5668\nOAuth<GithubAccess, GithubAccess.Wrong> oauth = new GithubOAuth(\n\t\"id\",\n\t\"secret\",\n\t\"https://exmaple.com/api/v0/login/oauth/github/callback\"\n);\n\n// \u751f\u6210\u6388\u6743 url\nString url = oauth.authorize();\n// \u751f\u6210\u5e26\u53c2\u6570\u6216\u6307\u5b9a scope\nString spec = oauth.authorize(List.of(\"email\"), Map.of(\"Accept\", \"application/json\"));\n \n//\u89e3\u6790\u56de\u8c03\u7684 url \u5e76\u83b7\u53d6 token\n// \u8f93\u5165\u539f\u59cb url \u81ea\u52a8\u89e3\u6790 code \u4ee5\u53ca state\noauth.token(\"url\");\n// \u66f4\u6539\u56de\u8c03\u5730\u5740\noauth.token(\"url\", \"redirect\");\n// \u624b\u52a8\u6307\u5b9a\u53c2\u6570\noauth.token(\"code\", \"state\", \"redirect\");\n \n// \u5904\u7406\u8fd4\u56de\u503c\noauth.token(\"code\", \"state\", \"redirect\")\n\t.succeed(data -> System.out.println(data.accessToken()))\n\t.fail(wrong -> System.out.println(wrong.errorDescription()))\n\t.except(throwable -> System.out.println(throwable.getMessage()));\n \n// \u5047\u8bbe\u8bf7\u6c42\u6210\u529f \u76f4\u63a5\u83b7\u53d6\u6570\u636e\nGithubAccess access = oauth.token(\"code\", \"state\", \"redirect\").data();\n
\n

\u4f7f\u7528 Socks \u4ee3\u7406

\n
oauth.proxy(() ->\n\tnew Request.Proxy(\n\t\tProxy.Type.SOCKS,\n\t\t\"127.0.0.1\",\n\t\t10086,\n\t\t\"username\",\n\t\t\"password\"\n\t)\n);\n
\n

\u66f4\u6362 State \u751f\u6210\u5668

\n

\u9ed8\u8ba4\u968f\u673a\u751f\u6210 UUID \u5e76\u8bbe\u7f6e 300 \u79d2\u6709\u6548\u671f

\n
oauth.state(\n Lazy.of(() -> new OAuthState(300, () -> UUID.randomUUID().toString()))\n);\n
\n

\u66f4\u6362 Http \u5ba2\u6237\u7aef

\n

\u9ed8\u8ba4\u4f7f\u7528 Okhttp \u53d1\u8d77\u8bf7\u6c42

\n
// \u5b9e\u73b0\u6bd4\u8f83\u7e41\u6742 \u5c31\u4e0d\u5c55\u793a\u5566 x\noauth.request(Lazy.of(OAuthRequest::new));\n
\n

\u66f4\u6362 Json \u89e3\u6790\u5668

\n

\u9ed8\u8ba4\u4f7f\u7528 Gson \u4f5c\u4e3a Json \u89e3\u6790\u5668

\n
oauth.serialization(\n\tLazy.of(() -> new Serialization() {\n\t\tfinal Gson gson = new Gson();\n\n\t\t@Override\n\t\tpublic <T> T object(Class<T> type, String raw) {\n\t\t\treturn gson.fromJson(raw, type);\n\t\t}\n\n\t\t@Override\n\t\tpublic <K, V> Map<K, V> map(Class<K> key, Class<V> value, String raw) {\n\t\t\treturn gson.fromJson(raw, new TypeToken<Map<K, V>>() {\n\t\t\t}.getType());\n\t\t}\n\n\t\t@Override\n\t\tpublic <T> List<T> list(Class<T> type, String raw) {\n\t\t\treturn gson.fromJson(raw, new TypeToken<List<T>>() {\n\t\t\t}.getType());\n\t\t}\n\t})\n);\n
\n", "date_published": "2023-01-06T12:56:39+00:00", "title": "Java \u5c0f\u5c0f\u5199\u4e2a\u5f00\u6e90 OAuth \u5ba2\u6237\u7aef\u5de5\u5177", "id": "t/907085" }, { "author": { "url": "member/botian", "name": "botian", "avatar": "https://cdn.v2ex.com/gravatar/79c20c838fcff8dcc81496b130dd43df?s=73&d=retro" }, "url": "t/545172", "title": "\u817e\u8baf\u7684\u7f51\u9875\u6388\u6743\u771f\u96be\u7533\u8bf7\uff0c\u5fae\u535a\u79d2\u641e\u5b9a\uff01", "id": "t/545172", "date_published": "2019-03-15T17:38:51+00:00", "content_html": "\u81ea\u5df1\u7684\u5c0f\u7f51\u7ad9\u63a5\u5165\u817e\u8baf\u6388\u6743\u767b\u9646\uff0c\u8d44\u6599\u5ba1\u6838\u72b6\u6001\uff0c\u5c45\u7136\u8fde\u6d4b\u8bd5\u673a\u4f1a\u90fd\u4e0d\u7ed9\uff0c\u5fae\u535a\u597d\u6b79\u8fd8\u80fd\u81ea\u6d4b\u4e0b\u3002" }, { "author": { "url": "member/Gonster", "name": "Gonster", "avatar": "https://cdn.v2ex.com/gravatar/73f60b2402794ba4a37c28d1c9562ff7?s=73&d=retro" }, "url": "t/276537", "date_modified": "2016-05-05T07:39:58+00:00", "content_html": "

WebView \u7684\u5b89\u5168\u95ee\u9898

\n

\u5f88\u591a\u624b\u673a app \u7528\u7b2c\u4e09\u65b9\u8eab\u4efd\u63d0\u4f9b\u5546\u901a\u8fc7 OAuth2.0 \uff08\u6216\u8005\u7c7b\u4f3c OpenID Connect \u7684\u65b9\u5f0f\uff09\u505a\u767b\u5f55\u7684\uff0c\u8eab\u4efd\u63d0\u4f9b\u5546\u4e00\u822c\u662f\u5141\u8bb8\u624b\u673a\u5e94\u7528\u767b\u5f55\u7684\u65f6\u5019\u7528 WebView \u6253\u5f00\u63d0\u4f9b\u5546\u7684\u767b\u5f55\u9875\u9762\u7684\u3002

\n

WebView \u7684\u8bf7\u6c42\u5185\u5bb9\u53ef\u4ee5\u88ab\u624b\u673a\u5e94\u7528\u62e6\u622a\uff0c\u90a3\u7528 OAuth2.0 \u7684\u610f\u4e49\u5462\uff0c\u5bc6\u7801\u4e0d\u662f\u4f1a\u88ab\u624b\u673a\u5e94\u7528\u83b7\u53d6\u5230\u5417\uff0c\u6216\u8005\u4e00\u822c\u50cf QQ \u8fd9\u4e9b\u662f\u9760\u4ed6\u4eec\u63d0\u4f9b\u7684 SDK \u4fdd\u8bc1\u5bc6\u7801\u5b89\u5168\u7684\u5417\uff1f

\n

installed native application \u76f8\u5173\u7684\u95ee\u9898

\n

\u6216\u8005\u8bf4\u662f\u5ba2\u6237\u7aef\u7c7b\u578b\u662f public \u7684\u76f8\u5173\u7684\u95ee\u9898\uff0c OAuth2.0 \u534f\u8bae\u91cc\u8ba4\u4e3a\u624b\u673a app \u8fd9\u7c7b\u7684\u7a0b\u5e8f\u662f\u4e0d\u80fd\u4fdd\u8bc1\u5ba2\u6237\u7aef\u5bc6\u7801\u5b89\u5168\u7684\u3002

\n

public \u7c7b\u578b\u7684\u5ba2\u6237\u7aef\u5982\u679c\u662f web app \u8fd8\u597d\uff0c\u5b83\u662f\u6709\u4e00\u4e2a\u56fa\u5b9a\u7684 URL \u7684\uff0c\u4e5f\u5c31\u662f\u8bf4\u901a\u8fc7redirect_uri\u80fd\u4fdd\u8bc1\u53ea\u6709\u8fd9\u4e2a web app \u80fd\u83b7\u5f97\u6388\u6743\u7801\uff0c\u6216\u8005\u8bf4\u4e5f\u80fd\u4fdd\u8bc1\u53ea\u6709\u8fd9\u4e2a\u7f51\u7ad9\u80fd\u7528\u8fd9\u4e2a\u5ba2\u6237\u7aef ID \u3002

\n

\u4f46\u662f\u672c\u5730\u5e94\u7528\u7a0b\u5e8f\u8fd9\u7c7b\u7684\uff0credirect_uri\u4e5f\u633a\u4e0d\u9760\u8c31\u7684:

\n
    \n
  1. \u6bd4\u5982\u5ba2\u6237\u7aef\u83b7\u5f97\u6388\u6743\u7801\u53ef\u80fd\u662f\u901a\u8fc7\u5728\u672c\u5730\u76d1\u542c\u67d0\u4e2a\u7aef\u53e3\uff0c\u53ef\u80fd\u5728\u6388\u6743\u670d\u52a1\u5668\u4e0a\u6ce8\u518c\u7684\u5c31\u662f127.0.0.1:port\u4e4b\u7c7b\u7684\u91cd\u5b9a\u5411 uri \u3002
  2. \n
  3. \u5ba2\u6237\u7aef\u5728\u672c\u5730\u6ce8\u518c\u4e00\u4e2a uri scheme \uff0c\u6388\u6743\u670d\u52a1\u5668\u4e0a\u6ce8\u518cscheme:XXXXX\u3002
  4. \n
  5. \u751a\u81f3\u6709\u4e9b\u60c5\u51b5\u4e0b\u662f\u5141\u8bb8\u7528\u6237\u6765\u62f7\u8d1d\u6388\u6743\u7801\u5230\u5ba2\u6237\u7aef\u91cc\u9762\u53bb\u7684\uff0c\u6bd4\u5982\u5728\u8fd9\u79cd\u60c5\u51b5 Google \u4f1a\u8ba9\u5ba2\u6237\u7aef\u4f7f\u7528urn:ietf:wg:oauth:2.0:oob\u8fd9\u6837\u7684redirect_uri\u6765\u6253\u5f00\u62f7\u8d1d\u6388\u6743\u7801\u7684\u9875\u9762\u3002
  6. \n
\n

\u8fd9\u4e9b\u5ba2\u6237\u7aef\u5728\u6388\u6743\u670d\u52a1\u5668\u4e0a\u6ce8\u518c\u7684\u610f\u4e49\u4f3c\u4e4e\u5e76\u4e0d\u662f\u5f88\u5927\u554a\uff0c\u800c\u4e14\u5982\u679c\u5ba2\u6237\u7aef ID \uff08\u5ba2\u6237\u7aef ID \u6ca1\u6709\u8981\u6c42\u8981\u4fdd\u5bc6\uff09\u88ab\u5176\u4ed6\u4eba\u83b7\u53d6\u4e86\u4ee5\u540e\uff0c\u5176\u4ed6\u4eba\u4e5f\u5f88\u6709\u53ef\u80fd\u80fd\u5192\u5145\u4f7f\u7528\u554a\u3002

\n

\u6216\u8005\u8bf4\u8fd9\u60c5\u51b5\u662f\u4e0d\u662f\u8fd8\u662f\u5e94\u8be5\u8ba9\u8fd9\u7c7b\u672c\u5730\u5b89\u88c5\u7684\u7a0b\u5e8f\u7684\u670d\u52a1\u5668\u7aef\u6765\u505a\u6388\u6743\uff0c\u8ba9\u7a0b\u5e8f\u548c\u4ed6\u7684\u670d\u52a1\u5668\u7aef\u6765\u901a\u4fe1\u66f4\u4f73\u5408\u9002\uff0c\u6216\u8005\u5ba2\u6237\u7aefID\u4e5f\u5e94\u8be5\u8981\u968f\u673a\u751f\u6210\u4e0d\u80fd\u968f\u610f\u904d\u5386\u548c\u9884\u6d4b\uff1f

\n", "date_published": "2016-05-05T07:35:09+00:00", "title": "\u5173\u4e8e native \u5e94\u7528\u7a0b\u5e8f\u5728\u4f7f\u7528 OAuth 2.0 \u7684\u4e00\u4e9b\u95ee\u9898", "id": "t/276537" }, { "author": { "url": "member/lepture", "name": "lepture", "avatar": "https://cdn.v2ex.com/avatar/b571/ecea/1205_large.png?m=1696251808" }, "url": "t/90239", "title": "\u5982\u4f55\u521b\u5efa\u4e00\u4e2a OAuth \u670d\u52a1", "id": "t/90239", "date_published": "2013-11-22T10:25:46+00:00", "content_html": "\u8fd9\u662f\u4e00\u7bc7 Python \u7684\u6559\u7a0b\uff1a

http://lepture.com/en/2013/create-oauth-server" }, { "author": { "url": "member/ksc010", "name": "ksc010", "avatar": "https://cdn.v2ex.com/avatar/e420/4b5b/37397_large.png?m=1774703771" }, "url": "t/77551", "date_modified": "2013-07-31T07:49:35+00:00", "content_html": "\u6700\u8fd1\u5728\u7814\u7a76\u5feb\u76d8\u7684api\uff0c\u6253\u7b97\u5199\u4e2alinux\u7ec8\u7aef\u4e0b\u7684\u5feb\u76d8\u5ba2\u6237\u7aef", "date_published": "2013-07-31T07:45:04+00:00", "title": "\u5728oauth1.0\u4e2d\u7b7e\u540d\u7684\u8bdd\u5fc5\u987b\u6709consumer_key \u4e0econsumer_secret \uff0c\u8fd9\u6837\u7684\u8bdd\u5728\u684c\u9762\u5e94\u7528\u4e2d\u5c82\u4e0d\u662f\u8fd9\u4e24\u4e2a\u90fd\u7ed9\u66b4\u6f0f\u4e86", "id": "t/77551" }, { "author": { "url": "member/Livid", "name": "Livid", "avatar": "https://cdn.v2ex.com/avatar/c4ca/4238/1_large.png?m=1775624785" }, "url": "t/70390", "title": "OAuth.io", "id": "t/70390", "date_published": "2013-05-28T04:40:26+00:00", "content_html": "http://oauth.io/

OAuth that just works." }, { "author": { "url": "member/Livid", "name": "Livid", "avatar": "https://cdn.v2ex.com/avatar/c4ca/4238/1_large.png?m=1775624785" }, "url": "t/69408", "title": "OAuth 2.0", "id": "t/69408", "date_published": "2013-05-19T09:50:08+00:00", "content_html": "" }, { "author": { "url": "member/techzhou", "name": "techzhou", "avatar": "https://cdn.v2ex.com/avatar/5ef9/9d16/5140_large.png?m=1684293075" }, "url": "t/38486", "title": "weibo\u7684OAuth\u95ee\u9898", "id": "t/38486", "date_published": "2012-06-05T11:38:30+00:00", "content_html": "\u5f00\u653e\u5e73\u53f0\u6587\u6863\u4e0a\u8bf4 OAuth2.0 access_token 24\u5c0f\u65f6\u540e\u8fc7\u671f

\u96be\u9053\u898124h\u4ee5\u540e \u518d\u6388\u6743\u4e00\u6b21 \u4e0d\u662f\u8fd9\u4e48\u5947\u8469\u5427" }, { "author": { "url": "member/fanzeyi", "name": "fanzeyi", "avatar": "https://cdn.v2ex.com/avatar/a9a1/d531/585_large.png?m=1491194258" }, "url": "t/16211", "date_modified": "2012-04-22T20:19:53+00:00", "content_html": "\u4e00\u76f4\u662f \u300cInvalid signature\u300d \u9519\u8bef.. \u3010\u7528\u7684 oauth \u5e93 http://oauth.googlecode.com/svn/code/python/oauth/oauth.py \r\n
\r\n
\u7136\u540e\u6211\u5c31\u9010\u884c\u7684\u68c0\u67e5 HMAC \u52a0\u5bc6\u7684\u4ee3\u7801.. \u53d1\u73b0\u6ca1\u6709\u4e00\u70b9\u95ee\u9898..\r\n
\r\n
\u5728 \u817e\u8baf\u5fae\u535a\u5f00\u653e\u5e73\u53f0\u7684\u8bba\u575b\u4e0a\u4e5f\u770b\u5230\u6709\u597d\u591a\u4eba\u51fa\u73b0\u8fd9\u4e2a\u95ee\u9898 \u4f3c\u4e4e\u662f\u548c urlencode \u6709\u5173 \u4f46\u662f\u5177\u4f53\u7684\u4e5f\u6ca1\u4eba\u7ed9\u51fa\u4e2a\u6b63\u786e\u7684\u89e3\u6cd5...\r\n
\r\n
\u5728 Github \u4e0a\u6709\u4e2a andelf/pyqqweibo \u7684 repo \u6211\u76f4\u63a5\u7ed9\u4ed6\u7684 oauth.py \u6539\u8fc7\u6765\u7528\u4e86 \u4f46\u662f\u8fd8\u662f\u4e00\u6837\u4e0d\u884c.. \r\n
\r\n
\u4e0b\u9762\u7684\u662f Signature Base String..\r\n
\r\n
GET&https%3A%2F%2Fopen.t.qq.com%2Fcgi-bin%2Frequest_token&oauth_callback%3Dnull%26oauth_consumer_key%3D11dca692584b4cc2835151b3c925ed1d%26oauth_nonce%3D93468450%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1311745309%26oauth_version%3D1.0\r\n
\r\n
\u5bc6\u5319\u90e8\u5206\u6211\u8bb0\u5f97\u5e26 & \u53f7\u4e86... \u6709\u641e\u8fc7 \u817e\u8bafOAuth\u7684\u561b \u6c42\u6559\uff01", "date_published": "2011-07-27T05:43:54+00:00", "title": "\u817e\u8baf\u5fae\u535a\u7684OAuth\u95ee\u9898......", "id": "t/16211" }, { "author": { "url": "member/Livid", "name": "Livid", "avatar": "https://cdn.v2ex.com/avatar/c4ca/4238/1_large.png?m=1775624785" }, "url": "t/900", "date_modified": "2012-04-21T21:54:06+00:00", "content_html": "\u6700\u8fd1\u7528 Python \u548c Objective-C \u5206\u522b\u641e\u5b9a\u4e86 OAuth/xAuth\uff0c\u5b9e\u5728\u662f\u592a\u723d\u4e86\u3002\u6574\u4e2a\u4e16\u754c\u5f00\u9614\u4e86\u3002", "date_published": "2010-07-25T02:17:45+00:00", "title": "\u641e\u5b9a OAuth \u7684\u611f\u89c9\u5b9e\u5728\u662f\u592a\u723d\u4e86", "id": "t/900" }, { "author": { "url": "member/Livid", "name": "Livid", "avatar": "https://cdn.v2ex.com/avatar/c4ca/4238/1_large.png?m=1775624785" }, "url": "t/884", "date_modified": "2012-04-21T22:35:25+00:00", "content_html": "\u53c2\u6570\u4e2d\u7684 oauth_token \u5e94\u8be5\u662f\u6307 access token \u5427\uff1f", "date_published": "2010-07-24T17:19:05+00:00", "title": "img.ly API", "id": "t/884" } ] } ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86