Add comments to exported methods for providers package

This commit is contained in:
Joel Speed 2018-12-20 10:37:59 +00:00
parent a65ceb2c41
commit e200bd5c20
No known key found for this signature in database
GPG Key ID: 6E80578D6751DEFB
11 changed files with 48 additions and 0 deletions

View File

@ -11,11 +11,13 @@ import (
"github.com/pusher/oauth2_proxy/api" "github.com/pusher/oauth2_proxy/api"
) )
// AzureProvider represents an Azure based Identity Provider
type AzureProvider struct { type AzureProvider struct {
*ProviderData *ProviderData
Tenant string Tenant string
} }
// NewAzureProvider initiates a new AzureProvider
func NewAzureProvider(p *ProviderData) *AzureProvider { func NewAzureProvider(p *ProviderData) *AzureProvider {
p.ProviderName = "Azure" p.ProviderName = "Azure"
@ -40,6 +42,7 @@ func NewAzureProvider(p *ProviderData) *AzureProvider {
return &AzureProvider{ProviderData: p} return &AzureProvider{ProviderData: p}
} }
// Configure defaults the AzureProvider configuration options
func (p *AzureProvider) Configure(tenant string) { func (p *AzureProvider) Configure(tenant string) {
p.Tenant = tenant p.Tenant = tenant
if tenant == "" { if tenant == "" {
@ -84,6 +87,7 @@ func getEmailFromJSON(json *simplejson.Json) (string, error) {
return email, err return email, err
} }
// GetEmailAddress returns the Account email address
func (p *AzureProvider) GetEmailAddress(s *SessionState) (string, error) { func (p *AzureProvider) GetEmailAddress(s *SessionState) (string, error) {
var email string var email string
var err error var err error

View File

@ -9,10 +9,12 @@ import (
"github.com/pusher/oauth2_proxy/api" "github.com/pusher/oauth2_proxy/api"
) )
// FacebookProvider represents an Facebook based Identity Provider
type FacebookProvider struct { type FacebookProvider struct {
*ProviderData *ProviderData
} }
// NewFacebookProvider initiates a new FacebookProvider
func NewFacebookProvider(p *ProviderData) *FacebookProvider { func NewFacebookProvider(p *ProviderData) *FacebookProvider {
p.ProviderName = "Facebook" p.ProviderName = "Facebook"
if p.LoginURL.String() == "" { if p.LoginURL.String() == "" {
@ -51,6 +53,7 @@ func getFacebookHeader(accessToken string) http.Header {
return header return header
} }
// GetEmailAddress returns the Account email address
func (p *FacebookProvider) GetEmailAddress(s *SessionState) (string, error) { func (p *FacebookProvider) GetEmailAddress(s *SessionState) (string, error) {
if s.AccessToken == "" { if s.AccessToken == "" {
return "", errors.New("missing access token") return "", errors.New("missing access token")
@ -75,6 +78,7 @@ func (p *FacebookProvider) GetEmailAddress(s *SessionState) (string, error) {
return r.Email, nil return r.Email, nil
} }
// ValidateSessionState validates the AccessToken
func (p *FacebookProvider) ValidateSessionState(s *SessionState) bool { func (p *FacebookProvider) ValidateSessionState(s *SessionState) bool {
return validateToken(p, s.AccessToken, getFacebookHeader(s.AccessToken)) return validateToken(p, s.AccessToken, getFacebookHeader(s.AccessToken))
} }

View File

@ -12,12 +12,14 @@ import (
"strings" "strings"
) )
// GitHubProvider represents an GitHub based Identity Provider
type GitHubProvider struct { type GitHubProvider struct {
*ProviderData *ProviderData
Org string Org string
Team string Team string
} }
// NewGitHubProvider initiates a new GitHubProvider
func NewGitHubProvider(p *ProviderData) *GitHubProvider { func NewGitHubProvider(p *ProviderData) *GitHubProvider {
p.ProviderName = "GitHub" p.ProviderName = "GitHub"
if p.LoginURL == nil || p.LoginURL.String() == "" { if p.LoginURL == nil || p.LoginURL.String() == "" {
@ -47,6 +49,8 @@ func NewGitHubProvider(p *ProviderData) *GitHubProvider {
} }
return &GitHubProvider{ProviderData: p} return &GitHubProvider{ProviderData: p}
} }
// SetOrgTeam adds GitHub org reading parameters to the OAuth2 scope
func (p *GitHubProvider) SetOrgTeam(org, team string) { func (p *GitHubProvider) SetOrgTeam(org, team string) {
p.Org = org p.Org = org
p.Team = team p.Team = team
@ -194,6 +198,7 @@ func (p *GitHubProvider) hasOrgAndTeam(accessToken string) (bool, error) {
return false, nil return false, nil
} }
// GetEmailAddress returns the Account email address
func (p *GitHubProvider) GetEmailAddress(s *SessionState) (string, error) { func (p *GitHubProvider) GetEmailAddress(s *SessionState) (string, error) {
var emails []struct { var emails []struct {
@ -251,6 +256,7 @@ func (p *GitHubProvider) GetEmailAddress(s *SessionState) (string, error) {
return "", nil return "", nil
} }
// GetUserName returns the Account user name
func (p *GitHubProvider) GetUserName(s *SessionState) (string, error) { func (p *GitHubProvider) GetUserName(s *SessionState) (string, error) {
var user struct { var user struct {
Login string `json:"login"` Login string `json:"login"`

View File

@ -8,10 +8,12 @@ import (
"github.com/pusher/oauth2_proxy/api" "github.com/pusher/oauth2_proxy/api"
) )
// GitLabProvider represents an GitLab based Identity Provider
type GitLabProvider struct { type GitLabProvider struct {
*ProviderData *ProviderData
} }
// NewGitLabProvider initiates a new GitLabProvider
func NewGitLabProvider(p *ProviderData) *GitLabProvider { func NewGitLabProvider(p *ProviderData) *GitLabProvider {
p.ProviderName = "GitLab" p.ProviderName = "GitLab"
if p.LoginURL == nil || p.LoginURL.String() == "" { if p.LoginURL == nil || p.LoginURL.String() == "" {
@ -41,6 +43,7 @@ func NewGitLabProvider(p *ProviderData) *GitLabProvider {
return &GitLabProvider{ProviderData: p} return &GitLabProvider{ProviderData: p}
} }
// GetEmailAddress returns the Account email address
func (p *GitLabProvider) GetEmailAddress(s *SessionState) (string, error) { func (p *GitLabProvider) GetEmailAddress(s *SessionState) (string, error) {
req, err := http.NewRequest("GET", req, err := http.NewRequest("GET",

View File

@ -20,6 +20,7 @@ import (
"google.golang.org/api/googleapi" "google.golang.org/api/googleapi"
) )
// GoogleProvider represents an Google based Identity Provider
type GoogleProvider struct { type GoogleProvider struct {
*ProviderData *ProviderData
RedeemRefreshURL *url.URL RedeemRefreshURL *url.URL
@ -28,6 +29,7 @@ type GoogleProvider struct {
GroupValidator func(string) bool GroupValidator func(string) bool
} }
// NewGoogleProvider initiates a new GoogleProvider
func NewGoogleProvider(p *ProviderData) *GoogleProvider { func NewGoogleProvider(p *ProviderData) *GoogleProvider {
p.ProviderName = "Google" p.ProviderName = "Google"
if p.LoginURL.String() == "" { if p.LoginURL.String() == "" {
@ -90,6 +92,7 @@ func emailFromIDToken(idToken string) (string, error) {
return email.Email, nil return email.Email, nil
} }
// Redeem exchanges the OAuth2 authentication token for an ID token
func (p *GoogleProvider) Redeem(redirectURL, code string) (s *SessionState, err error) { func (p *GoogleProvider) Redeem(redirectURL, code string) (s *SessionState, err error) {
if code == "" { if code == "" {
err = errors.New("missing code") err = errors.New("missing code")
@ -249,6 +252,8 @@ func (p *GoogleProvider) ValidateGroup(email string) bool {
return p.GroupValidator(email) return p.GroupValidator(email)
} }
// RefreshSessionIfNeeded checks if the session has expired and uses the
// RefreshToken to fetch a new ID token if required
func (p *GoogleProvider) RefreshSessionIfNeeded(s *SessionState) (bool, error) { func (p *GoogleProvider) RefreshSessionIfNeeded(s *SessionState) (bool, error) {
if s == nil || s.ExpiresOn.After(time.Now()) || s.RefreshToken == "" { if s == nil || s.ExpiresOn.After(time.Now()) || s.RefreshToken == "" {
return false, nil return false, nil

View File

@ -9,10 +9,12 @@ import (
"github.com/pusher/oauth2_proxy/api" "github.com/pusher/oauth2_proxy/api"
) )
// LinkedInProvider represents an LinkedIn based Identity Provider
type LinkedInProvider struct { type LinkedInProvider struct {
*ProviderData *ProviderData
} }
// NewLinkedInProvider initiates a new LinkedInProvider
func NewLinkedInProvider(p *ProviderData) *LinkedInProvider { func NewLinkedInProvider(p *ProviderData) *LinkedInProvider {
p.ProviderName = "LinkedIn" p.ProviderName = "LinkedIn"
if p.LoginURL.String() == "" { if p.LoginURL.String() == "" {
@ -47,6 +49,7 @@ func getLinkedInHeader(accessToken string) http.Header {
return header return header
} }
// GetEmailAddress returns the Account email address
func (p *LinkedInProvider) GetEmailAddress(s *SessionState) (string, error) { func (p *LinkedInProvider) GetEmailAddress(s *SessionState) (string, error) {
if s.AccessToken == "" { if s.AccessToken == "" {
return "", errors.New("missing access token") return "", errors.New("missing access token")
@ -69,6 +72,7 @@ func (p *LinkedInProvider) GetEmailAddress(s *SessionState) (string, error) {
return email, nil return email, nil
} }
// ValidateSessionState validates the AccessToken
func (p *LinkedInProvider) ValidateSessionState(s *SessionState) bool { func (p *LinkedInProvider) ValidateSessionState(s *SessionState) bool {
return validateToken(p, s.AccessToken, getLinkedInHeader(s.AccessToken)) return validateToken(p, s.AccessToken, getLinkedInHeader(s.AccessToken))
} }

View File

@ -10,17 +10,20 @@ import (
oidc "github.com/coreos/go-oidc" oidc "github.com/coreos/go-oidc"
) )
// OIDCProvider represents an OIDC based Identity Provider
type OIDCProvider struct { type OIDCProvider struct {
*ProviderData *ProviderData
Verifier *oidc.IDTokenVerifier Verifier *oidc.IDTokenVerifier
} }
// NewOIDCProvider initiates a new OIDCProvider
func NewOIDCProvider(p *ProviderData) *OIDCProvider { func NewOIDCProvider(p *ProviderData) *OIDCProvider {
p.ProviderName = "OpenID Connect" p.ProviderName = "OpenID Connect"
return &OIDCProvider{ProviderData: p} return &OIDCProvider{ProviderData: p}
} }
// Redeem exchanges the OAuth2 authentication token for an ID token
func (p *OIDCProvider) Redeem(redirectURL, code string) (s *SessionState, err error) { func (p *OIDCProvider) Redeem(redirectURL, code string) (s *SessionState, err error) {
ctx := context.Background() ctx := context.Background()
c := oauth2.Config{ c := oauth2.Config{
@ -73,6 +76,11 @@ func (p *OIDCProvider) Redeem(redirectURL, code string) (s *SessionState, err er
return return
} }
// RefreshSessionIfNeeded checks if the session has expired and uses the
// RefreshToken to fetch a new ID token if required
//
// WARNGING: This implementation is broken and does not check with the upstream
// OIDC provider before refreshing the session
func (p *OIDCProvider) RefreshSessionIfNeeded(s *SessionState) (bool, error) { func (p *OIDCProvider) RefreshSessionIfNeeded(s *SessionState) (bool, error) {
if s == nil || s.ExpiresOn.After(time.Now()) || s.RefreshToken == "" { if s == nil || s.ExpiresOn.After(time.Now()) || s.RefreshToken == "" {
return false, nil return false, nil

View File

@ -4,6 +4,8 @@ import (
"net/url" "net/url"
) )
// ProviderData contains information required to configure all implementations
// of OAuth2 providers
type ProviderData struct { type ProviderData struct {
ProviderName string ProviderName string
ClientID string ClientID string
@ -17,4 +19,5 @@ type ProviderData struct {
ApprovalPrompt string ApprovalPrompt string
} }
// Data returns the ProviderData
func (p *ProviderData) Data() *ProviderData { return p } func (p *ProviderData) Data() *ProviderData { return p }

View File

@ -12,6 +12,7 @@ import (
"github.com/pusher/oauth2_proxy/cookie" "github.com/pusher/oauth2_proxy/cookie"
) )
// Redeem provides a default implementation of the OAuth2 token redemption process
func (p *ProviderData) Redeem(redirectURL, code string) (s *SessionState, err error) { func (p *ProviderData) Redeem(redirectURL, code string) (s *SessionState, err error) {
if code == "" { if code == "" {
err = errors.New("missing code") err = errors.New("missing code")
@ -102,6 +103,7 @@ func (p *ProviderData) SessionFromCookie(v string, c *cookie.Cipher) (s *Session
return DecodeSessionState(v, c) return DecodeSessionState(v, c)
} }
// GetEmailAddress returns the Account email address
func (p *ProviderData) GetEmailAddress(s *SessionState) (string, error) { func (p *ProviderData) GetEmailAddress(s *SessionState) (string, error) {
return "", errors.New("not implemented") return "", errors.New("not implemented")
} }
@ -117,6 +119,7 @@ func (p *ProviderData) ValidateGroup(email string) bool {
return true return true
} }
// ValidateSessionState validates the AccessToken
func (p *ProviderData) ValidateSessionState(s *SessionState) bool { func (p *ProviderData) ValidateSessionState(s *SessionState) bool {
return validateToken(p, s.AccessToken, nil) return validateToken(p, s.AccessToken, nil)
} }

View File

@ -4,6 +4,7 @@ import (
"github.com/pusher/oauth2_proxy/cookie" "github.com/pusher/oauth2_proxy/cookie"
) )
// Provider represents an upstream identity provider implementation
type Provider interface { type Provider interface {
Data() *ProviderData Data() *ProviderData
GetEmailAddress(*SessionState) (string, error) GetEmailAddress(*SessionState) (string, error)
@ -17,6 +18,7 @@ type Provider interface {
CookieForSession(*SessionState, *cookie.Cipher) (string, error) CookieForSession(*SessionState, *cookie.Cipher) (string, error)
} }
// New provides a new Provider based on the configured provider string
func New(provider string, p *ProviderData) Provider { func New(provider string, p *ProviderData) Provider {
switch provider { switch provider {
case "linkedin": case "linkedin":

View File

@ -9,6 +9,7 @@ import (
"github.com/pusher/oauth2_proxy/cookie" "github.com/pusher/oauth2_proxy/cookie"
) )
// SessionState is used to store information about the currently authenticated user session
type SessionState struct { type SessionState struct {
AccessToken string AccessToken string
ExpiresOn time.Time ExpiresOn time.Time
@ -17,6 +18,7 @@ type SessionState struct {
User string User string
} }
// IsExpired checks whether the session has expired
func (s *SessionState) IsExpired() bool { func (s *SessionState) IsExpired() bool {
if !s.ExpiresOn.IsZero() && s.ExpiresOn.Before(time.Now()) { if !s.ExpiresOn.IsZero() && s.ExpiresOn.Before(time.Now()) {
return true return true
@ -24,6 +26,7 @@ func (s *SessionState) IsExpired() bool {
return false return false
} }
// String constructs a summary of the session state
func (s *SessionState) String() string { func (s *SessionState) String() string {
o := fmt.Sprintf("Session{%s", s.accountInfo()) o := fmt.Sprintf("Session{%s", s.accountInfo())
if s.AccessToken != "" { if s.AccessToken != "" {
@ -38,6 +41,7 @@ func (s *SessionState) String() string {
return o + "}" return o + "}"
} }
// EncodeSessionState returns string representation of the current session
func (s *SessionState) EncodeSessionState(c *cookie.Cipher) (string, error) { func (s *SessionState) EncodeSessionState(c *cookie.Cipher) (string, error) {
if c == nil || s.AccessToken == "" { if c == nil || s.AccessToken == "" {
return s.accountInfo(), nil return s.accountInfo(), nil
@ -49,6 +53,7 @@ func (s *SessionState) accountInfo() string {
return fmt.Sprintf("email:%s user:%s", s.Email, s.User) return fmt.Sprintf("email:%s user:%s", s.Email, s.User)
} }
// EncryptedString encrypts the session state into a cookie string
func (s *SessionState) EncryptedString(c *cookie.Cipher) (string, error) { func (s *SessionState) EncryptedString(c *cookie.Cipher) (string, error) {
var err error var err error
if c == nil { if c == nil {
@ -84,6 +89,7 @@ func decodeSessionStatePlain(v string) (s *SessionState, err error) {
return &SessionState{User: user, Email: email}, nil return &SessionState{User: user, Email: email}, nil
} }
// DecodeSessionState decodes the session cookie string into a SessionState
func DecodeSessionState(v string, c *cookie.Cipher) (s *SessionState, err error) { func DecodeSessionState(v string, c *cookie.Cipher) (s *SessionState, err error) {
if c == nil { if c == nil {
return decodeSessionStatePlain(v) return decodeSessionStatePlain(v)