--- a/login.go Wed May 10 11:06:22 2017 +0200
+++ b/login.go Wed May 10 13:07:00 2017 +0200
@@ -10,10 +10,14 @@
"encoding/json"
"strings"
+ "golang.org/x/oauth2"
+
"github.com/pkg/errors"
"github.com/sendgrid/rest"
)
+const oAuthRelPath = "/oauth/"
+
// UserToken represents a user token as returned by the Mastodon API
type UserToken struct {
AccessToken string `json:"access_token"`
@@ -50,7 +54,7 @@
}
req := rest.Request{
- BaseURL: mc.InstanceURL + "/oauth/token",
+ BaseURL: mc.InstanceURL + oAuthRelPath + "token",
Headers: hdrs,
QueryParams: opts,
Method: rest.Post,
@@ -86,3 +90,39 @@
}
return nil
}
+
+// LoginOAuth2 handles OAuth2 authentication
+// If code is empty, the URL to the server consent page will be returned;
+// if not, the user token is set.
+func (mc *Client) LoginOAuth2(code string, scopes []string) (string, error) {
+ if mc == nil {
+ return "", ErrUninitializedClient
+ }
+
+ conf := &oauth2.Config{
+ ClientID: mc.ID,
+ ClientSecret: mc.Secret,
+ Scopes: scopes,
+ Endpoint: oauth2.Endpoint{
+ AuthURL: mc.InstanceURL + oAuthRelPath + "authorize",
+ TokenURL: mc.InstanceURL + oAuthRelPath + "token",
+ },
+ RedirectURL: NoRedirect,
+ }
+
+ if code == "" {
+ // URL to consent page to ask for permission
+ // for the scopes specified above.
+ return conf.AuthCodeURL("state", oauth2.AccessTypeOffline), nil
+ }
+
+ // Return token
+ t, err := conf.Exchange(nil, code)
+ if err != nil {
+ return "", errors.Wrap(err, "cannot convert code into a token")
+ }
+ if t == nil || t.AccessToken == "" {
+ return "", errors.New("empty token")
+ }
+ return "", mc.SetUserToken(t.AccessToken, "", "", scopes)
+}