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 }