Golang Oauth2 Github
Github Oauth2
首先,在github上申请一个Oauth App, 获取client id / secret
需要这些信息,下边的代码是放在环境变量中
AUTH_URL = os.Getenv("AUTH_URL") // github authorization url
TOKEN_URL = os.Getenv("TOKEN_URL") // github token url
CLIENT_ID = os.Getenv("CLIENT_ID") // client id
CLIENT_SECRET = os.Getenv("CLIENT_SECRET") // client secret
REDIRECT_URL = os.Getenv("REDIRECT_URL") // the redirect url
在包的初始化代码中,初始化
var (
oauth2Config *oauth2.Config
)
init() {
oauth2Config = &oauth2.Config{
ClientID: CLIENT_ID,
ClientSecret: CLIENT_SECRET,
RedirectURL: REDIRECT_URL,
// Discovery returns the OAuth2 endpoints.
Endpoint: oauth2.Endpoint{
AuthURL: AUTH_URL,
TokenURL: TOKEN_URL,
AuthStyle: oauth2.AuthStyleInHeader,
},
Scopes: []string{"openid", "email", "site_admin", "repo", "admin:org", "user"},
}
Login handler
func HandleRedirect(w http.ResponseWriter, r *http.Request) {
//you need to generate random state here
http.Redirect(w, r, oauth2Config.AuthCodeURL(state), http.StatusFound)
}
callback handler
func HandleOAuth2Callback(w http.ResponseWriter, r *http.Request) {
log.Printf("Processing response")
state := r.URL.Query().Get("state")
target, ok := stateMap[state]
if !ok {
http.Error(w, "missing target in request", http.StatusBadRequest)
}
// remove from map
// delete(stateMap, state)
log.Printf("in HandleOAuth2Callback, target url : %s", target)
user, err := getUserInfo(r.FormValue("code"))
// create the user if not found
tNow := time.Now()
claims := jwt.StandardClaims{
Issuer: "CCMS Application",
Subject: user,
IssuedAt: tNow.Unix(),
ExpiresAt: tNow.Add(2 * time.Hour).Unix(), // two hours
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
ss, err := token.SignedString(jwtKey)
if err != nil {
http.Error(w, "Failed to sign the token : "+err.Error(), http.StatusInternalServerError)
return
}
rUrl := fmt.Sprintf("%s?token=%s", target, ss)
log.Printf("redirect to :%s", rUrl)
http.Redirect(w, r, rUrl, http.StatusFound)
the function to exchange code to get access token
func getUserInfo(code string) (string, error) {
token, err := oauth2Config.Exchange(oauth2.NoContext, code)
if err != nil {
return "", fmt.Errorf("code exchange failed: %s", err.Error())
}
ctx := context.Background()
log.Printf("access token: %+v", token)
// token.AccessToken --- this is the token you can use to call github api
return email, nil
}