You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

67 lines
1.7 KiB
Go

package mobilizon
import (
"context"
"encoding/base64"
"encoding/json"
"net/http"
"strings"
"time"
gql "github.com/hasura/go-graphql-client"
)
type bearerTokenTransport string
func (t bearerTokenTransport) RoundTrip(req *http.Request) (*http.Response, error) {
req.Header.Add("Authorization", "Bearer "+string(t))
return http.DefaultTransport.RoundTrip(req)
}
func (c *MobilizonClient) Authorize(email, pass string) (*User, error) {
var mut struct {
Login Login `graphql:"login(email: $email, password: $pass)"`
}
vars := map[string]interface{}{"email": String(email), "pass": String(pass)}
err := c.client.Mutate(context.Background(), &mut, vars)
if err != nil {
return nil, err
}
c.applyAuth(mut.Login.Auth)
return &mut.Login.User, nil
}
func (c *MobilizonClient) applyAuth(auth Auth) {
// FIXME: should set a mutex!
c.httpClient = &http.Client{
Transport: bearerTokenTransport(auth.AccessToken),
}
c.refreshToken = auth.RefreshToken
c.client = gql.NewClient(c.url, c.httpClient)
go func() {
time.Sleep(jwtExpiresIn(string(auth.AccessToken)) - 10*time.Second)
c.reauthorize(c.refreshToken)
}()
}
func (c *MobilizonClient) reauthorize(refreshToken String) error {
var mut struct {
Auth Auth `graphql:"refreshToken(refreshToken: $t)"`
}
vars := map[string]interface{}{"t": refreshToken}
err := c.client.Mutate(context.Background(), &mut, vars)
if err != nil {
return err
}
c.applyAuth(mut.Auth)
return nil
}
func jwtExpiresIn(token string) time.Duration {
jwtParts := strings.Split(token, ".")
jwtJson, _ := base64.RawStdEncoding.DecodeString(jwtParts[1])
var jwt struct{ Exp int64 }
json.Unmarshal([]byte(jwtJson), &jwt)
return time.Unix(jwt.Exp, 0).Sub(time.Now())
}