You've already forked oauth2-proxy
mirror of
https://github.com/oauth2-proxy/oauth2-proxy.git
synced 2025-12-01 22:51:45 +02:00
- Save both user and email in session state:
Encoding/decoding methods save both email and user
field in session state, for use cases when User is not derived from
email's local-parth, like for GitHub provider.
For retrocompatibility, if no user is obtained by the provider,
(e.g. User is an empty string) the encoding/decoding methods fall back
to the previous behavior and use the email's local-part
Updated also related tests and added two more tests to show behavior
when session contains a non-empty user value.
- Added first basic GitHub provider tests
- Added GetUserName method to Provider interface
The new GetUserName method is intended to return the User
value when this is not the email's local-part.
Added also the default implementation to provider_default.go
- Added call to GetUserName in redeemCode
the new GetUserName method is used in redeemCode
to get SessionState User value.
For backward compatibility, if GetUserName error is
"not implemented", the error is ignored.
- Added GetUserName method and tests to github provider.
120 lines
2.5 KiB
Go
120 lines
2.5 KiB
Go
package providers
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/bitly/oauth2_proxy/cookie"
|
|
)
|
|
|
|
type SessionState struct {
|
|
AccessToken string
|
|
ExpiresOn time.Time
|
|
RefreshToken string
|
|
Email string
|
|
User string
|
|
}
|
|
|
|
func (s *SessionState) IsExpired() bool {
|
|
if !s.ExpiresOn.IsZero() && s.ExpiresOn.Before(time.Now()) {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
func (s *SessionState) String() string {
|
|
o := fmt.Sprintf("Session{%s", s.accountInfo())
|
|
if s.AccessToken != "" {
|
|
o += " token:true"
|
|
}
|
|
if !s.ExpiresOn.IsZero() {
|
|
o += fmt.Sprintf(" expires:%s", s.ExpiresOn)
|
|
}
|
|
if s.RefreshToken != "" {
|
|
o += " refresh_token:true"
|
|
}
|
|
return o + "}"
|
|
}
|
|
|
|
func (s *SessionState) EncodeSessionState(c *cookie.Cipher) (string, error) {
|
|
if c == nil || s.AccessToken == "" {
|
|
return s.accountInfo(), nil
|
|
}
|
|
return s.EncryptedString(c)
|
|
}
|
|
|
|
func (s *SessionState) accountInfo() string {
|
|
return fmt.Sprintf("email:%s user:%s", s.Email, s.User)
|
|
}
|
|
|
|
func (s *SessionState) EncryptedString(c *cookie.Cipher) (string, error) {
|
|
var err error
|
|
if c == nil {
|
|
panic("error. missing cipher")
|
|
}
|
|
a := s.AccessToken
|
|
if a != "" {
|
|
if a, err = c.Encrypt(a); err != nil {
|
|
return "", err
|
|
}
|
|
}
|
|
r := s.RefreshToken
|
|
if r != "" {
|
|
if r, err = c.Encrypt(r); err != nil {
|
|
return "", err
|
|
}
|
|
}
|
|
return fmt.Sprintf("%s|%s|%d|%s", s.accountInfo(), a, s.ExpiresOn.Unix(), r), nil
|
|
}
|
|
|
|
func decodeSessionStatePlain(v string) (s *SessionState, err error) {
|
|
chunks := strings.Split(v, " ")
|
|
if len(chunks) != 2 {
|
|
return nil, fmt.Errorf("could not decode session state: expected 2 chunks got %d", len(chunks))
|
|
}
|
|
|
|
email := strings.TrimPrefix(chunks[0], "email:")
|
|
user := strings.TrimPrefix(chunks[1], "user:")
|
|
if user == "" {
|
|
user = strings.Split(email, "@")[0]
|
|
}
|
|
|
|
return &SessionState{User: user, Email: email}, nil
|
|
}
|
|
|
|
func DecodeSessionState(v string, c *cookie.Cipher) (s *SessionState, err error) {
|
|
if c == nil {
|
|
return decodeSessionStatePlain(v)
|
|
}
|
|
|
|
chunks := strings.Split(v, "|")
|
|
if len(chunks) != 4 {
|
|
err = fmt.Errorf("invalid number of fields (got %d expected 4)", len(chunks))
|
|
return
|
|
}
|
|
|
|
sessionState, err := decodeSessionStatePlain(chunks[0])
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if chunks[1] != "" {
|
|
if sessionState.AccessToken, err = c.Decrypt(chunks[1]); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
ts, _ := strconv.Atoi(chunks[2])
|
|
sessionState.ExpiresOn = time.Unix(int64(ts), 0)
|
|
|
|
if chunks[3] != "" {
|
|
if sessionState.RefreshToken, err = c.Decrypt(chunks[3]); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
return sessionState, nil
|
|
}
|