Menu

简易的内部单点登录系统思路

2018年10月26日 - Java Web 开发, SSO

简易概述

主要参考资料

要点

整个环节组成部分

client 系统注册需要填写

下文 demo 账号


授权码模式流程

用户未认证,业务系统触发授权码第一步

response_type=code
client_id=sso_client_test
redirect_uri=https://www.gitnavi.com/oauth/callback/aaaaaaaaaaa
state=SSSTTTAAAATTEEE

用户提交用户名和密码

业务系统回调地址端点,触发授权码第二步

grant_type=authorization_code
code=CCCCOOOODDDDEEEE
redirect_uri=https://www.gitnavi.com/oauth/callback
client_id=sso_client_test
client_secret=cccllliieeennnttsssseeecccrreeettt
请求参数合法,认证系统返回
{
  "access_token":"aaaaccccceeessssstttttoookkkeeennn",
  "token_type":"bearer",
  "expires_in":3600,
  "refresh_token":"rrrreeefffrrreeeessshhhtttoookkkeeennnn"
}
请求参数不合法,认证系统返回
{
  "error": "invalid_request",
  "error_description": "Request was missing the 'redirect_uri' parameter.",
  "error_uri": "See the full API docs at https://authorization-server.com/docs/access_token"
}

业务系统拿到 access_token

invalid_request (HTTP 400) – The request is missing a parameter, or is otherwise malformed.
invalid_token (HTTP 401) – The access token is expired, revoked, malformed, or invalid for other reasons. The client can obtain a new access token and try again.

通过 refresh_token,获取新的 access_token

grant_type=refresh_token
refresh_token=rrrreeefffrrreeeessshhhtttoookkkeeennnn
client_id=sso_client_test
client_secret=cccllliieeennnttsssseeecccrreeettt
请求参数合法,认证系统返回
{
  "access_token":"MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3",
  "token_type":"bearer",
  "expires_in":3600
}
请求参数不合法,认证系统返回
{
  "error": "invalid_request",
  "error_description": "Request was missing the 'redirect_uri' parameter.",
  "error_uri": "See the full API docs at https://authorization-server.com/docs/access_token"
}

验证 access_token / refresh_token 有效性

client_id=sso_client_test
client_secret=cccllliieeennnttsssseeecccrreeettt
token=aaaaccccceeessssstttttoookkkeeennn
token_type_hint=access_token
请求参数合法,并且是 access_token 类型,认证系统返回
{
    "active" : true,
    "token_type" : "bearer",
    "client_id" : "sso_client_test",
    "username" : "john.doe@example.com",
    "exp" : 1451606400,( token 过期时间,Unix 时间戳格式)
    "iat" : 1451602800(token 创建时间, Unix 时间戳格式。所以剩余多少时间,客户端要自己算)
}
请求参数合法,并且是 refresh_token 类型,认证系统返回
{
    "active" : true,
    "token_type" : "bearer",
    "client_id" : "sso_client_test",
    "username" : "john.doe@example.com",
    "exp" : 1451606400,( token 过期时间,Unix 时间戳格式)
    "iat" : 1451602800(token 创建时间, Unix 时间戳格式。所以剩余多少时间,客户端要自己算)
}
请求参数不合法,认证系统返回
{
    "error" : "invalid_client",
    "error_description" : "No client credentials found."
}

获取 access_token 对应的用户信息

请求参数合法,认证系统返回
{
  "sub": "00uid4BxXw6I6TV4m0g3",
  "name" :"John Doe",
  "nickname":"Jimmy",
  "given_name":"John",
  "middle_name":"James",
  "family_name":"Doe",
  "profile":"https://example.com/john.doe",
  "zoneinfo":"America/Los_Angeles",
  "locale":"en-US",
  "updated_at":1311280970,
  "email":"john.doe@example.com",
  "email_verified":true,
  "address" : { "street_address":"123 Hollywood Blvd.", "locality":"Los Angeles", "region":"CA", "postal_code":"90210", "country":"US" },
  "phone_number":"+1 (425) 555-1212"
}
请求参数不合法,认证系统返回
{
    "error" : "invalid_client",
    "error_description" : "No client credentials found."
}

业务系统触发登出


第三方接入,以 grafana 为例

[auth.generic_oauth]
enabled = true
client_id = sso_client_test
client_secret = cccllliieeennnttsssseeecccrreeettt
scopes =
auth_url = https://sso.youmeek.com/oauth/authorize
token_url = https://sso.youmeek.com/oauth/token
api_url = https://sso.youmeek.com/oauth/userinfo
allowed_domains = http://www.gitnavi.com
allow_sign_up = true