注冊
在https://github.com/settings/applications/new 注冊一個應用,擷取clientId 和 client secrets

通過github進行授權
前段頁面 通路:
<a href="https://github.com/login/oauth/authorize?client_id=e511f4733c56d5487d5d&redirect_uri=http://localhost:8087/oauth/redirect" target="_blank" rel="external nofollow" >
Login by GitHub
</a>
跳轉到github的授權頁面 确認授權,回調/oauth/redirect 通過傳遞參數code
(注意 href 的 redirect_uri 必須是在github上配置的 callback URL 比對,否則調用callback URL的時候不會傳遞code,提示錯誤。
關于redirect_uri ,這個redirect_uri 作為參數傳遞給githhub服務,github 會調用這個redirect_uri
redirect_uri 必須是和application上配置Authorization callback URL 一樣活着是它的子域名下。詳見:https://docs.github.com/en/developers/apps/building-oauth-apps/authorizing-oauth-apps#redirect-urls)
正常:
錯誤:
錯誤資訊:/oauth/redirect?error=redirect_uri_mismatch&error_description=The+redirect_uri+MUST+match+the+registered+callback+URL+for+this+application.&error_uri=https%3A%2F%2Fdocs.github.com%2Fapps%2Fmanaging-oauth-apps%2Ftroubleshooting-authorization-request-errors%2F%23redirect-uri-mismatch
回調伺服器端接口
伺服器端拿到這個code之後調用接口https://github.com/login/oauth/access_token?" +
"client_id=%s&client_secret=%s&code=%s 擷取accessToken。然後重定向到某個頁面
w.Header().Set("Location", "/hello.html?access_token="+t.AccessToken) 講token帶上。
http.HandleFunc("/oauth/redirect", func(w http.ResponseWriter, r *http.Request) {
err := r.ParseForm()
if err != nil {
fmt.Fprintf(os.Stdout, "could not parse query: %v", err)
w.WriteHeader(http.StatusBadRequest)
}
code := r.FormValue("code")
reqURL := fmt.Sprintf("https://github.com/login/oauth/access_token?" +
"client_id=%s&client_secret=%s&code=%s", clientID, clientSecret, code)
req, err := http.NewRequest(http.MethodPost, reqURL, nil)
if err != nil {
fmt.Fprintf(os.Stdout, "could not create HTTP request: %v", err)
w.WriteHeader(http.StatusBadRequest)
}
req.Header.Set("accept", "application/json")
res, err := httpClient.Do(req)
if err != nil {
fmt.Fprintf(os.Stdout, "could not send HTTP request: %v", err)
w.WriteHeader(http.StatusInternalServerError)
}
defer res.Body.Close()
var t AccessTokenResponse
if err := json.NewDecoder(res.Body).Decode(&t); err != nil {
fmt.Fprintf(os.Stdout, "could not parse JSON response: %v", err)
w.WriteHeader(http.StatusBadRequest)
}
w.Header().Set("Location", "/hello.html?access_token="+t.AccessToken)
w.WriteHeader(http.StatusFound)
})
拿到這個token之後,就可以調用github的使用者資訊接口:
頁面上調用
// 擷取access_token
const token = getQueryVariable("access_token");
// 調用使用者資訊接口
fetch('https://api.github.com/user', {
headers: {
Authorization: 'token ' + token
}
})
// 解析請求的JSON
.then(res => res.json())
.then(res => {
// 傳回使用者資訊
const nameNode = document.createTextNode(`Hi, ${res.login}, Welcome to login our site by GitHub!`)
document.body.appendChild(nameNode)
})
restclient 調用列印結果
傳回json格式的資料
{
"login": "xiaojianlee",
"id": 12822795,
"node_id": "MDQ6VXNlcjEyODIyNzk1",
"avatar_url": "https://avatars.githubusercontent.com/u/12822795?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/xiaojianlee",
"html_url": "https://github.com/xiaojianlee",
"followers_url": "https://api.github.com/users/xiaojianlee/followers",
"following_url": "https://api.github.com/users/xiaojianlee/following{/other_user}",
"gists_url": "https://api.github.com/users/xiaojianlee/gists{/gist_id}",
"starred_url": "https://api.github.com/users/xiaojianlee/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/xiaojianlee/subscriptions",
"organizations_url": "https://api.github.com/users/xiaojianlee/orgs",
"repos_url": "https://api.github.com/users/xiaojianlee/repos",
"events_url": "https://api.github.com/users/xiaojianlee/events{/privacy}",
"received_events_url": "https://api.github.com/users/xiaojianlee/received_events",
"type": "User",
"site_admin": false,
"name": null,
"company": null,
"blog": "",
"location": null,
"email": null,
"hireable": null,
"bio": null,
"twitter_username": null,
"public_repos": 7,
"public_gists": 0,
"followers": 0,
"following": 0,
"created_at": "2015-06-10T02:00:52Z",
"updated_at": "2021-06-29T13:39:15Z"
}