gauth

package module
v0.0.0-...-d82a2c7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 24, 2015 License: MIT Imports: 1 Imported by: 10

README

GAuth

Software License Build Status GoDoc

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

Provider Description Author Is Official?
AngelList Authenticate to AngelList using OAuth2. railsjedi No
Aol Authenticate to Aol using OAuth2. pianosnake No
App.net Authenticate to App.net using OAuth2. phuu No
Behance Authenticate to Behance using OAuth2. sandboxws No
Box Authenticate to Box using OAuth2. iCoreTech, Inc. No
Dropbox Authenticate to Dropbox using OAuth2. bamorim No
Facebook Authenticate to Facebook using OAuth2. tamnd No
Foursquare Authenticate to Foursquare using OAuth2. arunagw No
Instagram Authenticate to Instagram using OAuth2. tamnd No
Meetup Authenticate to Meetup using OAuth2. tapster No

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

Contact

License

The MIT License (MIT). Please see LICENSE for more information.

Copyright (c) 2015 Nguyen Duc Tam, tamnd87@gmail.com

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AccessToken

type AccessToken struct {
	// The Token
	Token     string
	Secret    string
	Expires   bool
	ExpiresAt time.Time
}

type Provider

type Provider interface {
	// AuthURL returns the login URL.
	AuthURL(state string) (requestToken string, loginURL string, err error)

	// Authorize gets an access token from verification code.
	Authorize(code string, params ...string) (*AccessToken, error)

	// User returns the authenticating user from the given access token.
	User(token *AccessToken) (*User, error)
}

type User

type User struct {
	ID          string
	Name        string
	Email       string
	Username    string
	Firstname   string
	Lastname    string
	Location    string
	Description string
	Avatar      string
	Phone       string
	Urls        map[string]string
	Raw         interface{}
}

User contains information about a user

Directories

Path Synopsis
provider
aol
box

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL