From e200bd5c20a085021e92b11ea1cfb1087e6e35bd Mon Sep 17 00:00:00 2001 From: Joel Speed Date: Thu, 20 Dec 2018 10:37:59 +0000 Subject: [PATCH] Add comments to exported methods for providers package --- providers/azure.go | 4 ++++ providers/facebook.go | 4 ++++ providers/github.go | 6 ++++++ providers/gitlab.go | 3 +++ providers/google.go | 5 +++++ providers/linkedin.go | 4 ++++ providers/oidc.go | 8 ++++++++ providers/provider_data.go | 3 +++ providers/provider_default.go | 3 +++ providers/providers.go | 2 ++ providers/session_state.go | 6 ++++++ 11 files changed, 48 insertions(+) diff --git a/providers/azure.go b/providers/azure.go index 4ec760c..f93db40 100644 --- a/providers/azure.go +++ b/providers/azure.go @@ -11,11 +11,13 @@ import ( "github.com/pusher/oauth2_proxy/api" ) +// AzureProvider represents an Azure based Identity Provider type AzureProvider struct { *ProviderData Tenant string } +// NewAzureProvider initiates a new AzureProvider func NewAzureProvider(p *ProviderData) *AzureProvider { p.ProviderName = "Azure" @@ -40,6 +42,7 @@ func NewAzureProvider(p *ProviderData) *AzureProvider { return &AzureProvider{ProviderData: p} } +// Configure defaults the AzureProvider configuration options func (p *AzureProvider) Configure(tenant string) { p.Tenant = tenant if tenant == "" { @@ -84,6 +87,7 @@ func getEmailFromJSON(json *simplejson.Json) (string, error) { return email, err } +// GetEmailAddress returns the Account email address func (p *AzureProvider) GetEmailAddress(s *SessionState) (string, error) { var email string var err error diff --git a/providers/facebook.go b/providers/facebook.go index 42d3ce3..6f81f15 100644 --- a/providers/facebook.go +++ b/providers/facebook.go @@ -9,10 +9,12 @@ import ( "github.com/pusher/oauth2_proxy/api" ) +// FacebookProvider represents an Facebook based Identity Provider type FacebookProvider struct { *ProviderData } +// NewFacebookProvider initiates a new FacebookProvider func NewFacebookProvider(p *ProviderData) *FacebookProvider { p.ProviderName = "Facebook" if p.LoginURL.String() == "" { @@ -51,6 +53,7 @@ func getFacebookHeader(accessToken string) http.Header { return header } +// GetEmailAddress returns the Account email address func (p *FacebookProvider) GetEmailAddress(s *SessionState) (string, error) { if s.AccessToken == "" { return "", errors.New("missing access token") @@ -75,6 +78,7 @@ func (p *FacebookProvider) GetEmailAddress(s *SessionState) (string, error) { return r.Email, nil } +// ValidateSessionState validates the AccessToken func (p *FacebookProvider) ValidateSessionState(s *SessionState) bool { return validateToken(p, s.AccessToken, getFacebookHeader(s.AccessToken)) } diff --git a/providers/github.go b/providers/github.go index a307658..d39ee2b 100644 --- a/providers/github.go +++ b/providers/github.go @@ -12,12 +12,14 @@ import ( "strings" ) +// GitHubProvider represents an GitHub based Identity Provider type GitHubProvider struct { *ProviderData Org string Team string } +// NewGitHubProvider initiates a new GitHubProvider func NewGitHubProvider(p *ProviderData) *GitHubProvider { p.ProviderName = "GitHub" if p.LoginURL == nil || p.LoginURL.String() == "" { @@ -47,6 +49,8 @@ func NewGitHubProvider(p *ProviderData) *GitHubProvider { } return &GitHubProvider{ProviderData: p} } + +// SetOrgTeam adds GitHub org reading parameters to the OAuth2 scope func (p *GitHubProvider) SetOrgTeam(org, team string) { p.Org = org p.Team = team @@ -194,6 +198,7 @@ func (p *GitHubProvider) hasOrgAndTeam(accessToken string) (bool, error) { return false, nil } +// GetEmailAddress returns the Account email address func (p *GitHubProvider) GetEmailAddress(s *SessionState) (string, error) { var emails []struct { @@ -251,6 +256,7 @@ func (p *GitHubProvider) GetEmailAddress(s *SessionState) (string, error) { return "", nil } +// GetUserName returns the Account user name func (p *GitHubProvider) GetUserName(s *SessionState) (string, error) { var user struct { Login string `json:"login"` diff --git a/providers/gitlab.go b/providers/gitlab.go index 83df5e2..446727d 100644 --- a/providers/gitlab.go +++ b/providers/gitlab.go @@ -8,10 +8,12 @@ import ( "github.com/pusher/oauth2_proxy/api" ) +// GitLabProvider represents an GitLab based Identity Provider type GitLabProvider struct { *ProviderData } +// NewGitLabProvider initiates a new GitLabProvider func NewGitLabProvider(p *ProviderData) *GitLabProvider { p.ProviderName = "GitLab" if p.LoginURL == nil || p.LoginURL.String() == "" { @@ -41,6 +43,7 @@ func NewGitLabProvider(p *ProviderData) *GitLabProvider { return &GitLabProvider{ProviderData: p} } +// GetEmailAddress returns the Account email address func (p *GitLabProvider) GetEmailAddress(s *SessionState) (string, error) { req, err := http.NewRequest("GET", diff --git a/providers/google.go b/providers/google.go index 113a691..36283f2 100644 --- a/providers/google.go +++ b/providers/google.go @@ -20,6 +20,7 @@ import ( "google.golang.org/api/googleapi" ) +// GoogleProvider represents an Google based Identity Provider type GoogleProvider struct { *ProviderData RedeemRefreshURL *url.URL @@ -28,6 +29,7 @@ type GoogleProvider struct { GroupValidator func(string) bool } +// NewGoogleProvider initiates a new GoogleProvider func NewGoogleProvider(p *ProviderData) *GoogleProvider { p.ProviderName = "Google" if p.LoginURL.String() == "" { @@ -90,6 +92,7 @@ func emailFromIDToken(idToken string) (string, error) { 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) { if code == "" { err = errors.New("missing code") @@ -249,6 +252,8 @@ func (p *GoogleProvider) ValidateGroup(email string) bool { 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) { if s == nil || s.ExpiresOn.After(time.Now()) || s.RefreshToken == "" { return false, nil diff --git a/providers/linkedin.go b/providers/linkedin.go index e6de34e..8c392f8 100644 --- a/providers/linkedin.go +++ b/providers/linkedin.go @@ -9,10 +9,12 @@ import ( "github.com/pusher/oauth2_proxy/api" ) +// LinkedInProvider represents an LinkedIn based Identity Provider type LinkedInProvider struct { *ProviderData } +// NewLinkedInProvider initiates a new LinkedInProvider func NewLinkedInProvider(p *ProviderData) *LinkedInProvider { p.ProviderName = "LinkedIn" if p.LoginURL.String() == "" { @@ -47,6 +49,7 @@ func getLinkedInHeader(accessToken string) http.Header { return header } +// GetEmailAddress returns the Account email address func (p *LinkedInProvider) GetEmailAddress(s *SessionState) (string, error) { if s.AccessToken == "" { return "", errors.New("missing access token") @@ -69,6 +72,7 @@ func (p *LinkedInProvider) GetEmailAddress(s *SessionState) (string, error) { return email, nil } +// ValidateSessionState validates the AccessToken func (p *LinkedInProvider) ValidateSessionState(s *SessionState) bool { return validateToken(p, s.AccessToken, getLinkedInHeader(s.AccessToken)) } diff --git a/providers/oidc.go b/providers/oidc.go index 0c0fa52..9624826 100644 --- a/providers/oidc.go +++ b/providers/oidc.go @@ -10,17 +10,20 @@ import ( oidc "github.com/coreos/go-oidc" ) +// OIDCProvider represents an OIDC based Identity Provider type OIDCProvider struct { *ProviderData Verifier *oidc.IDTokenVerifier } +// NewOIDCProvider initiates a new OIDCProvider func NewOIDCProvider(p *ProviderData) *OIDCProvider { p.ProviderName = "OpenID Connect" 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) { ctx := context.Background() c := oauth2.Config{ @@ -73,6 +76,11 @@ func (p *OIDCProvider) Redeem(redirectURL, code string) (s *SessionState, err er 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) { if s == nil || s.ExpiresOn.After(time.Now()) || s.RefreshToken == "" { return false, nil diff --git a/providers/provider_data.go b/providers/provider_data.go index 92e27dd..ff752c3 100644 --- a/providers/provider_data.go +++ b/providers/provider_data.go @@ -4,6 +4,8 @@ import ( "net/url" ) +// ProviderData contains information required to configure all implementations +// of OAuth2 providers type ProviderData struct { ProviderName string ClientID string @@ -17,4 +19,5 @@ type ProviderData struct { ApprovalPrompt string } +// Data returns the ProviderData func (p *ProviderData) Data() *ProviderData { return p } diff --git a/providers/provider_default.go b/providers/provider_default.go index 01a2060..f8f59ab 100644 --- a/providers/provider_default.go +++ b/providers/provider_default.go @@ -12,6 +12,7 @@ import ( "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) { if 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) } +// GetEmailAddress returns the Account email address func (p *ProviderData) GetEmailAddress(s *SessionState) (string, error) { return "", errors.New("not implemented") } @@ -117,6 +119,7 @@ func (p *ProviderData) ValidateGroup(email string) bool { return true } +// ValidateSessionState validates the AccessToken func (p *ProviderData) ValidateSessionState(s *SessionState) bool { return validateToken(p, s.AccessToken, nil) } diff --git a/providers/providers.go b/providers/providers.go index ad5f1e8..15e6421 100644 --- a/providers/providers.go +++ b/providers/providers.go @@ -4,6 +4,7 @@ import ( "github.com/pusher/oauth2_proxy/cookie" ) +// Provider represents an upstream identity provider implementation type Provider interface { Data() *ProviderData GetEmailAddress(*SessionState) (string, error) @@ -17,6 +18,7 @@ type Provider interface { CookieForSession(*SessionState, *cookie.Cipher) (string, error) } +// New provides a new Provider based on the configured provider string func New(provider string, p *ProviderData) Provider { switch provider { case "linkedin": diff --git a/providers/session_state.go b/providers/session_state.go index c2ae9f4..fcac6e9 100644 --- a/providers/session_state.go +++ b/providers/session_state.go @@ -9,6 +9,7 @@ import ( "github.com/pusher/oauth2_proxy/cookie" ) +// SessionState is used to store information about the currently authenticated user session type SessionState struct { AccessToken string ExpiresOn time.Time @@ -17,6 +18,7 @@ type SessionState struct { User string } +// IsExpired checks whether the session has expired func (s *SessionState) IsExpired() bool { if !s.ExpiresOn.IsZero() && s.ExpiresOn.Before(time.Now()) { return true @@ -24,6 +26,7 @@ func (s *SessionState) IsExpired() bool { return false } +// String constructs a summary of the session state func (s *SessionState) String() string { o := fmt.Sprintf("Session{%s", s.accountInfo()) if s.AccessToken != "" { @@ -38,6 +41,7 @@ func (s *SessionState) String() string { return o + "}" } +// EncodeSessionState returns string representation of the current session func (s *SessionState) EncodeSessionState(c *cookie.Cipher) (string, error) { if c == nil || s.AccessToken == "" { return s.accountInfo(), nil @@ -49,6 +53,7 @@ func (s *SessionState) accountInfo() string { 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) { var err error if c == nil { @@ -84,6 +89,7 @@ func decodeSessionStatePlain(v string) (s *SessionState, err error) { 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) { if c == nil { return decodeSessionStatePlain(v)