Documentation
¶
Overview ¶
Package goauth is a simple to use and implement tool to configure OAuth authentication for your application or service. It relies on some of the OAuth tools already available for Go, but adds in some structure to reduce the complexity of your implementation. The intent is to make authentication easy by reducing the pain points to just a couple of configuration parameters.
This package provides two OAuth implementations, Version 1.0 and Version 2.0. For version 2.0 implementations the sequence of events is fairly straightforward.
Browser Server Provider | | | # GET: /oauth/provider | | #==>==>==>==>==>==>==>==>=># | | Send Redirect # | #<=<==<==<==<==<==<==<==<==# | # Redirect to provider login | #==>==>==>==>==>==>==>==>==|==>==>==>==>==>==>==>==>=># | | # User logs in | | Redirect to callback URL # #<=<==<==<==<==<==<==<==<==|==<==<==<==<==<==<==<==<==# # GET: Callback URL | | #==>==>==>==>==>==>==>==>=># | | # GET: User Info | | #==>==>==>==>==>==>==>==>=># | #<=<==<==<==<==<==<==<==<==# | # Process User | | # Create Session | | Respond To User # | #<=<==<==<==<==<==<==<==<==# | # | |
For version 1.0 implementations the sequence of events is slightly more complex, however most of that complexity is hidden from you by the API.
Browser Server Provider | | | # GET: /oauth/provider | | #==>==>==>==>==>==>==>==>=># | | # Fetch OAuth Token | | #==>==>==>==>==>==>==>==>=># | # # Auth Request | # Return Token and Secret # | #<=<==<==<==<==<==<==<==<==# | Send Redirect # | #<=<==<==<==<==<==<==<==<==# | # Redirect to provider login | #==>==>==>==>==>==>==>==>==|==>==>==>==>==>==>==>==>=># | | # User logs in | | Redirect to callback URL # #<=<==<==<==<==<==<==<==<==|==<==<==<==<==<==<==<==<==# # GET: Callback URL | | #==>==>==>==>==>==>==>==>=># | | # Fetch Access Token | | #==>==>==>==>==>==>==>==>=># | # # Auth Request | # Return Access Token # | #<=<==<==<==<==<==<==<==<==# | # GET: User Info | | #==>==>==>==>==>==>==>==>=># | #<=<==<==<==<==<==<==<==<==# | # Process User | | # Create Session | | Respond To User # | #<=<==<==<==<==<==<==<==<==# | # | |
Index ¶
- Constants
- func ConfigureProvidersFromJSON(fileReader io.Reader, callbackURL string) (map[string]OAuthServiceProvider, error)
- func ConfigureProvidersFromYAML(fileReader io.Reader, callbackURL string) (map[string]OAuthServiceProvider, error)
- type OAuth1ServiceProvider
- type OAuth1ServiceProviderConfig
- type OAuth2ServiceProvider
- type OAuth2ServiceProviderConfig
- type OAuthServiceProvider
- type UserData
Examples ¶
Constants ¶
const ( OAuth1HeaderTransmissionType = 1 << iota OAuth1QueryParamTramssionType = 1 << iota OAuth1DefaultTransmissionType = OAuth1HeaderTransmissionType )
OAuth 1.0 authentication transmission types.
const ( OAuthVerbGet = "GET" OAuthVerbPost = "POST" OAuthVerbDefault = OAuthVerbPost )
OAuth 1.0 Verbs.
const ( OAuthVersion1 = "1.0" OAuthVersion2 = "2.0" )
OAuth Versions.
Variables ¶
This section is empty.
Functions ¶
func ConfigureProvidersFromJSON ¶
func ConfigureProvidersFromJSON(fileReader io.Reader, callbackURL string) (map[string]OAuthServiceProvider, error)
ConfigureProvidersFromJSON configures a map of providers using a JSON file.
Example ¶
// in this example I'm hiding the client ID and secret which will be fetched // from the environment. os.Setenv("GOOGLE_CLIENT_ID", "abc123") os.Setenv("GOOGLE_CLIENT_SECRET", "xyz456") os.Setenv("FACEBOOK_CLIENT_ID", "abc123") os.Setenv("FACEBOOK_CLIENT_SECRET", "xyz456") os.Setenv("TWITTER_CLIENT_ID", "abc123") os.Setenv("TWITTER_CLIENT_SECRET", "xyz456") jsonString := `{ "Google":{ "OAuthVersion":2.0, "AuthURL":"https://accounts.google.com/o/oauth2/auth", "TokenURL":"https://accounts.google.com/o/oauth2/token", "UserInfoURL":"https://www.googleapis.com/oauth2/v2/userinfo", "Scopes":[ "https://www.googleapis.com/auth/userinfo.profile", "https://www.googleapis.com/auth/userinfo.email" ] }, "Facebook":{ "OAuthVersion":2.0, "AuthURL":"https://www.facebook.com/dialog/oauth", "TokenURL":"https://graph.facebook.com/oauth/access_token", "UserInfoURL":"https://graph.facebook.com/me?fields=id,first_name,middle_name,last_name,email,picture", "Scopes":[ "email", "public_profile" ] }, "Twitter":{ "OAuthVersion":1.0, "AuthURL":"https://api.twitter.com/oauth/authorize", "TokenURL":"https://api.twitter.com/oauth/access_token", "UserInfoURL":"https://api.twitter.com/1.1/account/verify_credentials.json", "RequestTokenURL":"https://api.twitter.com/oauth/request_token" } }` reader := strings.NewReader(jsonString) providers, err := ConfigureProvidersFromJSON(reader, "http://myhost/oauth/callback/%v") if err != nil { fmt.Println(err.Error()) } fmt.Printf("Found %d providers.\n", len(providers)) fmt.Printf("The provider for %s is a version %s provider named %s.\n", "google", providers["google"].GetOAuthVersion(), providers["google"].GetProviderName()) fmt.Printf("The provider for %s is a version %s provider named %s.\n", "facebook", providers["facebook"].GetOAuthVersion(), providers["facebook"].GetProviderName()) fmt.Printf("The provider for %s is a version %s provider named %s.\n", "twitter", providers["twitter"].GetOAuthVersion(), providers["twitter"].GetProviderName())
Output: Found 3 providers. The provider for google is a version 2.0 provider named GOOGLE. The provider for facebook is a version 2.0 provider named FACEBOOK. The provider for twitter is a version 1.0 provider named TWITTER.
func ConfigureProvidersFromYAML ¶
func ConfigureProvidersFromYAML(fileReader io.Reader, callbackURL string) (map[string]OAuthServiceProvider, error)
ConfigureProvidersFromYAML configures a map of providers using a YAML file.
Example ¶
yamlString := `GOOGLE: OAuthVersion: 2.0 AuthURL: https://accounts.google.com/o/oauth2/auth TokenURL: https://accounts.google.com/o/oauth2/token UserInfoURL: https://www.googleapis.com/oauth2/v2/userinfo ClientID: abcxyz ClientSecret: 123098abcxyz Scopes: - https://www.googleapis.com/auth/userinfo.profile - https://www.googleapis.com/auth/userinfo.email FACEBOOK: OAuthVersion: 2.0 AuthURL: https://www.facebook.com/dialog/oauth TokenURL: https://graph.facebook.com/oauth/access_token UserInfoURL: https://graph.facebook.com/me?fields=id,first_name,middle_name,last_name,email,picture ClientID: abcxyz ClientSecret: 123098abcxyz Scopes: - email - public_profile TWITTER: OAuthVersion: 1.0 AuthURL: https://api.twitter.com/oauth/authorize TokenURL: https://api.twitter.com/oauth/access_token UserInfoURL: https://api.twitter.com/1.1/account/verify_credentials.json RequestTokenURL: https://api.twitter.com/oauth/request_token ClientID: abcxyz ClientSecret: 123098abcxyz` reader := strings.NewReader(yamlString) providers, err := ConfigureProvidersFromYAML(reader, "http://myhost/oauth/callback/%v") if err != nil { fmt.Println(err.Error()) } fmt.Printf("Found %d providers.\n", len(providers)) fmt.Printf("The provider for %s is a version %s provider named %s.\n", "google", providers["google"].GetOAuthVersion(), providers["google"].GetProviderName()) fmt.Printf("The provider for %s is a version %s provider named %s.\n", "facebook", providers["facebook"].GetOAuthVersion(), providers["facebook"].GetProviderName()) fmt.Printf("The provider for %s is a version %s provider named %s.\n", "twitter", providers["twitter"].GetOAuthVersion(), providers["twitter"].GetProviderName())
Output: Found 3 providers. The provider for google is a version 2.0 provider named GOOGLE. The provider for facebook is a version 2.0 provider named FACEBOOK. The provider for twitter is a version 1.0 provider named TWITTER.
Types ¶
type OAuth1ServiceProvider ¶
type OAuth1ServiceProvider struct {
// contains filtered or unexported fields
}
OAuth1ServiceProvider is an implementation of the OAuthServiceProvider interface for use in OAuth Version 1.0 authentication.
func (*OAuth1ServiceProvider) GetOAuthVersion ¶
func (provider *OAuth1ServiceProvider) GetOAuthVersion() string
GetOAuthVersion gets the version of OAuth implemented by this provider.
func (*OAuth1ServiceProvider) GetProviderName ¶
func (provider *OAuth1ServiceProvider) GetProviderName() string
GetProviderName gets the name of of the OAuth provider.
func (*OAuth1ServiceProvider) GetRedirectURL ¶
func (provider *OAuth1ServiceProvider) GetRedirectURL() (string, error)
GetRedirectURL is called when the user first requests to authenticate via OAuth. The URL that is returned is the URL that the user should be redirected to in order to supply the provider with credentials. As an example, if the user is attempting to authenticate via Facebook's API, the user would need to be redirected to Facebook's authentication page.
func (*OAuth1ServiceProvider) ProcessResponse ¶
func (provider *OAuth1ServiceProvider) ProcessResponse(request *http.Request) (UserData, error)
ProcessResponse is called after the user has been successfully authenticated. This method will receive a message back from the OAuth provider containing information about the now authenticated user.
type OAuth1ServiceProviderConfig ¶
type OAuth1ServiceProviderConfig struct { // ProviderName is the name of the provider (eg: Google) ProviderName string // ClientID every provider assigns a client id and a secret key. ClientID string // ClientSecret every provider assigns a client id and a secret key, // this is the secret key. ClientSecret string // AuthURL is the authentication URL. AuthURL string // TokenURL is the URL that assigns an access token to the user. TokenURL string // UserInfoVerb is the verb used to request user information. Usually one of "GET" or // "POST". Defaults to GET. UserInfoVerb string // UserInfoURL is the URL to fetch user data from, once the user is authenticated. UserInfoURL string // RequestTokenVerb is the verb used to fetch the oauth token information. Usually one of // "GET" or "POST". Defaults to POST. RequestTokenVerb string // RequestTokenURL is the URL used to fetch the oauth token. RequestTokenURL string // AuthTransmissionType is the type of transmission used to transport authentication information. // Usually either as query parameters in the Authentication header. // Defaults to Header. AuthTransmissionType int // RedirectURL is the URL where the browser should be sent after authentication. // Often this URL is also provider specific // (eg: http://myserver.com/oauth/callback/[provider_name]). RedirectURL string }
OAuth1ServiceProviderConfig is a simple struct which can be used to initialize an OAuth1ServiceProvider.
type OAuth2ServiceProvider ¶
type OAuth2ServiceProvider struct {
// contains filtered or unexported fields
}
OAuth2ServiceProvider is an implementation of the OAuthServiceProvider interface for use in OAuth Version 2.0 authentication.
func (*OAuth2ServiceProvider) GetOAuthVersion ¶
func (provider *OAuth2ServiceProvider) GetOAuthVersion() string
GetOAuthVersion gets the version of OAuth implemented by this provider.
func (*OAuth2ServiceProvider) GetProviderName ¶
func (provider *OAuth2ServiceProvider) GetProviderName() string
GetProviderName gets the name of of the OAuth provider.
func (*OAuth2ServiceProvider) GetRedirectURL ¶
func (provider *OAuth2ServiceProvider) GetRedirectURL() (string, error)
GetRedirectURL is called when the user first requests to authenticate via OAuth. The URL that is returned is the URL that the user should be redirected to in order to supply the provider with credentials. As an example, if the user is attempting to authenticate via Facebook's API, the user would need to be redirected to Facebook's authentication page.
func (*OAuth2ServiceProvider) ProcessResponse ¶
func (provider *OAuth2ServiceProvider) ProcessResponse(request *http.Request) (UserData, error)
ProcessResponse is called after the user has been successfully authenticated. This method will receive a message back from the OAuth provider containing information about the now authenticated user.
type OAuth2ServiceProviderConfig ¶
type OAuth2ServiceProviderConfig struct { // ProviderName is the name of the provider (eg: Google) ProviderName string // ClientID every provider assigns a client id and a secret key. ClientID string // ClientSecret every provider assigns a client id and a secret key, // this is the secret key. ClientSecret string // AuthURL is the authentication URL. AuthURL string // TokenURL is the URL that assigns a token to the user. TokenURL string // UserInfoURL is the URL to fetch user data from, once the user is authenticated. UserInfoURL string // RedirectURL is the URL where the browser should be sent after authentication. // Often this URL is also provider specific // (eg: http://myserver.com/oauth/callback/[provider_name]). RedirectURL string // Scopes are a list of user details requested. Each provider has // their own list of scopes. Scopes []string }
OAuth2ServiceProviderConfig is a simple struct which can be used to initialize an OAuth2ServiceProvider.
type OAuthServiceProvider ¶
type OAuthServiceProvider interface { // GetRedirectURL is called when the user first requests to authenticate via OAuth. // The URL that is returned is the URL that the user should be redirected to in // order to supply the provider with credentials. As an example, if the user is // attempting to authenticate via Facebook's API, the user would need to be // redirected to Facebook's authentication page. GetRedirectURL() (string, error) // ProcessResponse is called after the user has been successfully authenticated. // This method will receive a message back from the OAuth provider containing // information about the now authenticated user. ProcessResponse(requet *http.Request) (UserData, error) // GetOAuthVersion gets the version of OAuth implemented by this provider. GetOAuthVersion() string // GetProviderName gets the name of of the OAuth provider. GetProviderName() string }
OAuthServiceProvider is the base class for this library. This is where all of the real work is done. Instances of the this class call the methods necessary to perform the authentication proceedures.
Example ¶
googleConf := OAuth2ServiceProviderConfig{ ProviderName: "GOOGLE", ClientID: os.Getenv("GOOGLE_CLIENT_ID"), ClientSecret: os.Getenv("GOOGLE_CLIENT_SECRET"), AuthURL: "https://accounts.google.com/o/oauth2/auth", TokenURL: "https://accounts.google.com/o/oauth2/token", UserInfoURL: "https://www.googleapis.com/oauth2/v2/userinfo", RedirectURL: "http://myserver.com/oauth/callback/google", Scopes: []string{"https://www.googleapis.com/auth/userinfo.profile", "https://www.googleapis.com/auth/userinfo.email"}, } twitterConf := OAuth1ServiceProviderConfig{ ProviderName: "TWITTER", ClientID: os.Getenv("TWITTER_CLIENT_ID"), ClientSecret: os.Getenv("TWITTER_CLIENT_SECRET"), AuthURL: "https://api.twitter.com/oauth/authorize", TokenURL: "https://api.twitter.com/oauth/access_token", UserInfoURL: "https://api.twitter.com/1.1/account/verify_credentials.json", RequestTokenURL: "https://api.twitter.com/oauth/request_token", RedirectURL: "http://myserver.com/oauth/callback/twitter", // THE FOLLOWING ARE DEFAULT VALUES // UserInfoVerb: OAuthVerbGet, // RequestTokenVerb: OAuthVerbPost, // AuthTransmissionType: OAuth1HeaderTransmissionType, } googleProvider := NewOAuth2ServiceProvider(googleConf) twitterProvider := NewOAuth1ServiceProvider(twitterConf) http.HandleFunc("/homepage", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte(`<html><body><h1>HURRAY</h1></body></html>`)) }) // register providers with http handler http.HandleFunc("/oauth/authenticate/google", func(w http.ResponseWriter, r *http.Request) { redirectURL, _ := googleProvider.GetRedirectURL() http.Redirect(w, r, redirectURL, 302) }) http.HandleFunc("/oauth/authenticate/twitter", func(w http.ResponseWriter, r *http.Request) { redirectURL, _ := twitterProvider.GetRedirectURL() http.Redirect(w, r, redirectURL, 302) }) // register response handlers http.HandleFunc("/oauth/callback/google", func(w http.ResponseWriter, r *http.Request) { userData, err := googleProvider.ProcessResponse(r) if err != nil { http.Error(w, err.Error(), 500) } else { var sessionID string log.Printf("Found user %v", userData.String()) // create a user session // redirect user to new page with a session id http.Redirect(w, r, "/homepage?sessionID="+url.QueryEscape(sessionID), 302) } }) http.HandleFunc("/oauth/callback/twitter", func(w http.ResponseWriter, r *http.Request) { userData, err := twitterProvider.ProcessResponse(r) if err != nil { http.Error(w, err.Error(), 500) } else { var sessionID string log.Printf("Found user %v", userData.String()) // create a user session // redirect user to new page with a session id http.Redirect(w, r, "/homepage?sessionID="+url.QueryEscape(sessionID), 302) } }) http.ListenAndServe(":9000", nil)
Output:
func NewOAuth1ServiceProvider ¶
func NewOAuth1ServiceProvider(config OAuth1ServiceProviderConfig) OAuthServiceProvider
NewOAuth1ServiceProvider initializes a new OAuth 2.0 service provider.
func NewOAuth2ServiceProvider ¶
func NewOAuth2ServiceProvider(config OAuth2ServiceProviderConfig) OAuthServiceProvider
NewOAuth2ServiceProvider initializes a new OAuth 2.0 service provider.
type UserData ¶
type UserData struct { UserID string Email string FullName string GivenName string FamilyName string ScreenName string PhotoURL string OAuthProvider string OAuthVersion string OAuthToken string OAuthTokenType string }
UserData is a wrapper for the output of the authorization process. The UserData struct will have as much information about the user as this service can provide. This means that not all properties of this struct will be set.