mirror of https://github.com/writeas/writefreely
Merge pull request #317 from pascoual/feature/generic-oauth
Login with generic oauth feature++pull/376/head
commit
dfa14c9c92
@ -0,0 +1,114 @@ |
|||||||
|
package writefreely |
||||||
|
|
||||||
|
import ( |
||||||
|
"context" |
||||||
|
"errors" |
||||||
|
"net/http" |
||||||
|
"net/url" |
||||||
|
"strings" |
||||||
|
) |
||||||
|
|
||||||
|
type genericOauthClient struct { |
||||||
|
ClientID string |
||||||
|
ClientSecret string |
||||||
|
AuthLocation string |
||||||
|
ExchangeLocation string |
||||||
|
InspectLocation string |
||||||
|
CallbackLocation string |
||||||
|
HttpClient HttpClient |
||||||
|
} |
||||||
|
|
||||||
|
var _ oauthClient = genericOauthClient{} |
||||||
|
|
||||||
|
const ( |
||||||
|
genericOauthDisplayName = "OAuth" |
||||||
|
) |
||||||
|
|
||||||
|
func (c genericOauthClient) GetProvider() string { |
||||||
|
return "generic" |
||||||
|
} |
||||||
|
|
||||||
|
func (c genericOauthClient) GetClientID() string { |
||||||
|
return c.ClientID |
||||||
|
} |
||||||
|
|
||||||
|
func (c genericOauthClient) GetCallbackLocation() string { |
||||||
|
return c.CallbackLocation |
||||||
|
} |
||||||
|
|
||||||
|
func (c genericOauthClient) buildLoginURL(state string) (string, error) { |
||||||
|
u, err := url.Parse(c.AuthLocation) |
||||||
|
if err != nil { |
||||||
|
return "", err |
||||||
|
} |
||||||
|
q := u.Query() |
||||||
|
q.Set("client_id", c.ClientID) |
||||||
|
q.Set("redirect_uri", c.CallbackLocation) |
||||||
|
q.Set("response_type", "code") |
||||||
|
q.Set("state", state) |
||||||
|
q.Set("scope", "read_user") |
||||||
|
u.RawQuery = q.Encode() |
||||||
|
return u.String(), nil |
||||||
|
} |
||||||
|
|
||||||
|
func (c genericOauthClient) exchangeOauthCode(ctx context.Context, code string) (*TokenResponse, error) { |
||||||
|
form := url.Values{} |
||||||
|
form.Add("grant_type", "authorization_code") |
||||||
|
form.Add("redirect_uri", c.CallbackLocation) |
||||||
|
form.Add("scope", "read_user") |
||||||
|
form.Add("code", code) |
||||||
|
req, err := http.NewRequest("POST", c.ExchangeLocation, strings.NewReader(form.Encode())) |
||||||
|
if err != nil { |
||||||
|
return nil, err |
||||||
|
} |
||||||
|
req.WithContext(ctx) |
||||||
|
req.Header.Set("User-Agent", "writefreely") |
||||||
|
req.Header.Set("Accept", "application/json") |
||||||
|
req.Header.Set("Content-Type", "application/x-www-form-urlencoded") |
||||||
|
req.SetBasicAuth(c.ClientID, c.ClientSecret) |
||||||
|
|
||||||
|
resp, err := c.HttpClient.Do(req) |
||||||
|
if err != nil { |
||||||
|
return nil, err |
||||||
|
} |
||||||
|
if resp.StatusCode != http.StatusOK { |
||||||
|
return nil, errors.New("unable to exchange code for access token") |
||||||
|
} |
||||||
|
|
||||||
|
var tokenResponse TokenResponse |
||||||
|
if err := limitedJsonUnmarshal(resp.Body, tokenRequestMaxLen, &tokenResponse); err != nil { |
||||||
|
return nil, err |
||||||
|
} |
||||||
|
if tokenResponse.Error != "" { |
||||||
|
return nil, errors.New(tokenResponse.Error) |
||||||
|
} |
||||||
|
return &tokenResponse, nil |
||||||
|
} |
||||||
|
|
||||||
|
func (c genericOauthClient) inspectOauthAccessToken(ctx context.Context, accessToken string) (*InspectResponse, error) { |
||||||
|
req, err := http.NewRequest("GET", c.InspectLocation, nil) |
||||||
|
if err != nil { |
||||||
|
return nil, err |
||||||
|
} |
||||||
|
req.WithContext(ctx) |
||||||
|
req.Header.Set("User-Agent", "writefreely") |
||||||
|
req.Header.Set("Accept", "application/json") |
||||||
|
req.Header.Set("Authorization", "Bearer "+accessToken) |
||||||
|
|
||||||
|
resp, err := c.HttpClient.Do(req) |
||||||
|
if err != nil { |
||||||
|
return nil, err |
||||||
|
} |
||||||
|
if resp.StatusCode != http.StatusOK { |
||||||
|
return nil, errors.New("unable to inspect access token") |
||||||
|
} |
||||||
|
|
||||||
|
var inspectResponse InspectResponse |
||||||
|
if err := limitedJsonUnmarshal(resp.Body, infoRequestMaxLen, &inspectResponse); err != nil { |
||||||
|
return nil, err |
||||||
|
} |
||||||
|
if inspectResponse.Error != "" { |
||||||
|
return nil, errors.New(inspectResponse.Error) |
||||||
|
} |
||||||
|
return &inspectResponse, nil |
||||||
|
} |
Loading…
Reference in new issue