OAuth is a specification that allows users to delegate access to their data without sharing their username and password with that service.

Learn how to implement authentication via Google in a Go web application.

First things first, we need to create our Google Project and create OAuth2 credentials.

Code

oauth2.Config example

Go: oauth2.Config
1
2
3
4
5
6
7
8
9
10
googleOauth2Conf = &oauth2.Config{
	ClientID:     "your_google_client_id",
	ClientSecret: "your_google_client_secret",
	RedirectURL:  "http://localhost:8080/auth/google/callback",
	Scopes: []string{
		"profile",
		"email",
	},
	Endpoint: google.Endpoint,
}

Generate state

Go: Generate state
1
2
3
b := make([]byte, 16)
_, _ = rand.Read(b)
state := base64.URLEncoding.EncodeToString(b)

Get AuthCodeURL with state

Go: AuthCodeURL
1
gotoUrl := googleOauth2Conf.AuthCodeURL(state)

Save state at server and Redirect to gotoUrl, which will redirect us to the google login page.

Go: Redirect
1
2
SetCookie("state", state)
Redirect(gotoUrl, 302)

After login with our google credentials, it will redirect back to our application and on the callback page, we can see the details of the logged-in user and can save this detail in a database for future use also.

Do in OAuthGoogleCallBack Handler

Get state from cookie and check it with the value from FormValue

Go: check state
1
2
3
4
5
6
7
stateCookie := getCookie("state")
stateForm := r.FormValue("state")

if stateCookie != stateForm {
    // invalid state
    return
}

Get code from FormValue and Exchange Token with code.

Go: get token
1
2
code := r.FormValue("code")
token, err := googleOauth2Conf.Exchange(context.Background(), code)

Get user info with token

Go: Get user info with token
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
oauthGoogleUrlAPI := "https://www.googleapis.com/oauth2/v2/userinfo?access_token="

client := googleOauth2Conf.Client(context.Background(), token)
response, err := client.Get(oauthGoogleUrlAPI + token.AccessToken)
if err != nil {
	// err
	return
}
defer response.Body.Close()
contents, err := ioutil.ReadAll(response.Body)
if err != nil {
	// err
	return
}
log.Println(string(contents))

ToDo with user info

Register or Login with the logined User info.

Reference