github.com/johnnyeven/libtools@v0.0.0-20191126065708-61829c1adf46/oauth2/g7/g7.go (about)

     1  package g7
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/base64"
     6  	"net/url"
     7  	"strings"
     8  
     9  	"github.com/johnnyeven/libtools/conf"
    10  	"github.com/johnnyeven/libtools/conf/presets"
    11  	"github.com/johnnyeven/libtools/courier/client"
    12  )
    13  
    14  type OAuth struct {
    15  	ClientID     string           `conf:"env"`
    16  	ClientSecret presets.Password `conf:"env"`
    17  	RedirectURL  string           `conf:"env"`
    18  	Scopes       []string
    19  	client.Client
    20  }
    21  
    22  func (o OAuth) DockerDefaults() conf.DockerDefaults {
    23  	return conf.DockerDefaults{
    24  		"Host": "oauth.chinawayltd.com",
    25  	}
    26  }
    27  
    28  func (o OAuth) MarshalDefaults(v interface{}) {
    29  	if oauth, ok := v.(*OAuth); ok {
    30  		if oauth.Host == "" {
    31  			oauth.Host = "oauth.chinawayltd.com"
    32  		}
    33  	}
    34  }
    35  
    36  func (o *OAuth) authURL(baseURL, state string) string {
    37  	var buf bytes.Buffer
    38  	buf.WriteString(baseURL)
    39  	v := url.Values{
    40  		"response_type": {"code"},
    41  		"client_id":     {o.ClientID},
    42  		"redirect_uri":  {o.RedirectURL},
    43  		"scope":         {strings.Join(o.Scopes, " ")},
    44  		"state":         {state},
    45  	}
    46  	if strings.Contains(baseURL, "?") {
    47  		buf.WriteByte('&')
    48  	} else {
    49  		buf.WriteByte('?')
    50  	}
    51  	buf.WriteString(v.Encode())
    52  	return buf.String()
    53  }
    54  
    55  func (o *OAuth) AuthCodeURL(state string) string {
    56  	return o.authURL(o.Client.GetBaseURL("http")+"/oauth/authorize", state)
    57  }
    58  
    59  func (o *OAuth) LogoutURL(state string) string {
    60  	return o.authURL(o.Client.GetBaseURL("http")+"/oauth/v0/logout", state)
    61  }
    62  
    63  type TokenRequest struct {
    64  	// `Basic ${base64(client_id+":"+"client_secret")}`
    65  	Authorization string `name:"Authorization" in:"header"`
    66  	// required when grant_type=authorization_code
    67  	Code string `name:"code" in:"formData"`
    68  	// required when grant_type=refresh_token
    69  	RefreshToken string `name:"refresh_token" in:"formData"`
    70  	// authorization_code | password | client_credentials | refresh_token
    71  	GrantType string `name:"grant_type" in:"formData"`
    72  	// required when grant_type=password
    73  	Username string `name:"username" in:"formData"`
    74  	// required when grant_type=password
    75  	Password string `name:"password" in:"formData"`
    76  }
    77  
    78  func (o *OAuth) Exchange(code string) (token *Token, err error) {
    79  	token = &Token{}
    80  	req := TokenRequest{
    81  		GrantType:     "authorization_code",
    82  		Code:          code,
    83  		Authorization: "Basic " + basicAuth(o.ClientID, o.ClientSecret.String()),
    84  	}
    85  	err = o.Request("oauth.Token", "POST", "/oauth/token", req).
    86  		Do().
    87  		Into(token)
    88  	return
    89  }
    90  
    91  type CheckTokenRequest struct {
    92  	// `Basic ${base64(client_id+":"+"client_secret")}`
    93  	Authorization string `name:"Authorization" in:"header"`
    94  	// AccessToken
    95  	AccessToken string `name:"access_token" in:"query"`
    96  }
    97  
    98  func (o OAuth) Validate(accessToken string) (token *Token, err error) {
    99  	token = &Token{}
   100  	req := CheckTokenRequest{
   101  		AccessToken:   accessToken,
   102  		Authorization: "Basic " + basicAuth(o.ClientID, o.ClientSecret.String()),
   103  	}
   104  	err = o.Request("oauth.CheckToken", "GET", "/oauth/token", req).
   105  		Do().
   106  		Into(token)
   107  	return
   108  }
   109  
   110  type Token struct {
   111  	TokenType   string `json:"token_type" default:"bearer"`
   112  	AccessToken string `json:"access_token"`
   113  	// 单位 s
   114  	ExpiresIn    int64  `json:"expires_in"`
   115  	RefreshToken string `json:"refresh_token"`
   116  	User
   117  }
   118  
   119  type User struct {
   120  	ID uint64 `json:"id" redis:"id"`
   121  	// ldap user
   122  	Username       string `json:"username,omitempty"`
   123  	Name           string `json:"name,omitempty"`
   124  	OrgName        string `json:"org_name,omitempty"`
   125  	GithubUsername string `json:"github_username,omitempty"`
   126  	DingtalkID     string `json:"dingtalk_id,omitempty"`
   127  	DingtalkNick   string `json:"dingtalk_nick,omitempty"`
   128  }
   129  
   130  func basicAuth(username, password string) string {
   131  	auth := username + ":" + password
   132  	return base64.StdEncoding.EncodeToString([]byte(auth))
   133  }