GAuth
Clean way to write authentication for Go.
This package was inspired by https://github.com/intridea/omniauth (written in Ruby) and http://github.com/markbates/goth (written in Go).
Features
- Support both OAuth 1.0a and OAuth2
- Have a long list of providers and is easy to write new ones.
Install
$ go get github.com/tamnd/gauth
List of Providers
Here are the list of supported providers. Would you love to see more providers? Feel free to contribute ones by create your own repository or create pull requests!
I use the list as reference. When porting providers directly from those gems, I also keep the author of the gems as author of the providers.
Please keep the list in alphabetical order
Usage
First, import GAuth and create OAuth provider
import (
"github.com/tamnd/gauth"
"github.com/tamnd/gauth/provider/facebook"
)
// Create facebook provider
var provider = facebook.New("FACEBOOK_KEY", "FACEBOOK_CLIENT_SECRET", "http://localhost:8080/auth/facebook/callback")
Next, define a handler for GET /auth/facebook
. This will redirect the user to the facebook login page.
func login(w http.ResponseWriter, r *http.Request) {
authURL, _, err := provider.AuthURL("state")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
http.Redirect(w, r, authURL, http.StatusTemporaryRedirect)
}
Then define the handler for callback request at /auth/facebook/callback
:
func callback(w http.ResponseWriter, r *http.Request) {
code := r.URL.Query().Get("code")
// Get access token from verification code.
token, err := provider.Authorize(code)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// Get the authenticating user
user, err := provider.User(token)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// Marshal user info and write to the response.
output, _ := json.Marshal(user)
w.Write([]byte(output))
}
Finally, we register those handlers and start the server:
func main() {
fmt.Println("Start listening on :8080")
http.Handle("/auth/facebook", http.HandlerFunc(login))
http.Handle("/auth/facebook/callback", http.HandlerFunc(callback))
http.ListenAndServe(":8080", nil)
}
See the full source code at examples/facebook.go.
Write new provider
Writing new provider is pretty easy. You just need to define OAuth endpoints:
package yoursite
import "github.com/tamnd/gauth/oauth2"
var Endpoint = oauth2.Endpoint{
AuthURL: "https://yoursite.com/oauth2/auth",
TokenURL: "https://yoursite.com/oauth2/token",
}
and define a function User
to get user info from an access token:
package yoursite
import "github.com/tamnd/gauth"
func User(token *gauth.AccessToken) (*gauth.User, error) {
// Get the user info here...
}
For example, here is the Facebook Authentication Provider:
provider/facebook/facebook.go
package facebook
import (
"github.com/tamnd/gauth"
"github.com/tamnd/gauth/oauth2"
)
var Endpoint = oauth2.Endpoint{
AuthURL: "https://www.facebook.com/dialog/oauth",
TokenURL: "https://graph.facebook.com/oauth/access_token",
}
func New(clientId string, secret string, callbackURL string, scopes ...string) gauth.Provider {
provider := &oauth2.Provider{
Endpoint: Endpoint,
UserFn: User,
}
provider.Init(clientId, secret, callbackURL)
return provider
}
provider/facebook/user.go
package facebook
import (
"net/url"
"github.com/tamnd/gauth"
"github.com/tamnd/httpclient"
)
var endpointProfile = "https://graph.facebook.com/me?fields=email,first_name,last_name,link,bio,id,name,picture,location"
func User(token *gauth.AccessToken) (*gauth.User, error) {
URL := endpointProfile + "&access_token=" + url.QueryEscape(token.Token)
u := struct {
ID string `json:"id"`
Email string `json:"email"`
Bio string `json:"bio"`
Name string `json:"name"`
Link string `json:"link"`
Picture struct {
Data struct {
URL string `json:"url"`
} `json:"data"`
} `json:"picture"`
Location struct {
Name string `json:"name"`
} `json:"location"`
}{}
err := httpclient.JSON(URL, &u)
if err != nil {
return nil, err
}
user := gauth.User{
ID: u.ID,
Name: u.Name,
Email: u.Email,
Username: u.Name,
Location: u.Location.Name,
Description: u.Bio,
Avatar: u.Picture.Data.URL,
Raw: u,
}
return &user, nil
}
Contribute
- Fork repository
- Create a feature branch
- Open a new pull request
- Create an issue for bug report or feature request
License
The MIT License (MIT). Please see LICENSE for more information.
Copyright (c) 2015 Nguyen Duc Tam, tamnd87@gmail.com