mirror of https://git.sr.ht/~sircmpwn/gql.sr.ht
OAuth 2.0 Bearer: check revocation status
This commit is contained in:
parent
9c4efafa16
commit
0395c9720d
|
@ -1,6 +1,7 @@
|
|||
package auth
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/sha512"
|
||||
"database/sql"
|
||||
|
@ -8,6 +9,7 @@ import (
|
|||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
|
@ -20,6 +22,7 @@ import (
|
|||
"github.com/vaughan0/go-ini"
|
||||
"github.com/vektah/gqlparser/gqlerror"
|
||||
|
||||
"git.sr.ht/~sircmpwn/gql.sr.ht/config"
|
||||
"git.sr.ht/~sircmpwn/gql.sr.ht/crypto"
|
||||
"git.sr.ht/~sircmpwn/gql.sr.ht/database"
|
||||
)
|
||||
|
@ -256,7 +259,7 @@ func OAuth2(db *sql.DB, token string, hash [64]byte,
|
|||
// until they were necessary (e.g. resolving query { me })
|
||||
|
||||
query := database.
|
||||
Select(context.TODO(), []string{
|
||||
Select(r.Context(), []string{
|
||||
`u.id`, `u.username`,
|
||||
`u.created`, `u.updated`,
|
||||
`u.email`,
|
||||
|
@ -301,9 +304,89 @@ func OAuth2(db *sql.DB, token string, hash [64]byte,
|
|||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
// Fetch revocation status for this token
|
||||
|
||||
// TODO: Check if this token or client has been revoked
|
||||
atomic.AddInt32(&res, 1)
|
||||
conf := config.ForContext(r.Context())
|
||||
meta, ok := conf.Get("meta.sr.ht", "origin")
|
||||
if !ok {
|
||||
panic(errors.New("No meta.sr.ht origin specified in config.ini"))
|
||||
}
|
||||
|
||||
type GraphQLQuery struct {
|
||||
Query string `json:"query"`
|
||||
Variables map[string]interface{} `json:"variables"`
|
||||
}
|
||||
type GraphQLResponse struct {
|
||||
Data struct {
|
||||
RevocationStatus bool `json:"tokenRevocationStatus"`
|
||||
} `json:"data"`
|
||||
}
|
||||
|
||||
query := GraphQLQuery{
|
||||
Query: `
|
||||
query RevocationStatus($hash: String!, $clientId: String) {
|
||||
tokenRevocationStatus(hash: $hash, clientId: $clientId)
|
||||
}`,
|
||||
Variables: map[string]interface{} {
|
||||
"hash": hex.EncodeToString(hash[:]),
|
||||
"clientId": ot.ClientID,
|
||||
},
|
||||
}
|
||||
|
||||
body, err := json.Marshal(query)
|
||||
if err != nil {
|
||||
panic(err) // Programmer error
|
||||
}
|
||||
|
||||
reader := bytes.NewBuffer(body)
|
||||
req, err := http.NewRequestWithContext(r.Context(),
|
||||
"POST", fmt.Sprintf("%s/query", meta), reader)
|
||||
if err != nil {
|
||||
log.Printf("http.NewRequest: %e")
|
||||
return
|
||||
}
|
||||
req.Header.Add("Content-Type", "application/json")
|
||||
auth := InternalAuth{
|
||||
Name: ot.Username,
|
||||
// TODO: Populate these better
|
||||
ClientID: "gql.sr.ht",
|
||||
NodeID: "gql.sr.ht",
|
||||
}
|
||||
authBlob, err := json.Marshal(&auth)
|
||||
if err != nil {
|
||||
panic(err) // Programmer error
|
||||
}
|
||||
req.Header.Add("Authorization", fmt.Sprintf("Internal %s",
|
||||
crypto.Encrypt(authBlob)))
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
log.Printf("http.Do: %e", err)
|
||||
return
|
||||
}
|
||||
|
||||
defer resp.Body.Close()
|
||||
|
||||
respBody, err := ioutil.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
log.Printf("ioutil.ReadAll: %e")
|
||||
return
|
||||
}
|
||||
|
||||
if resp.StatusCode != 200 {
|
||||
log.Printf("meta.sr.ht returned status %d: %s",
|
||||
resp.StatusCode, string(respBody))
|
||||
return
|
||||
}
|
||||
|
||||
var result GraphQLResponse
|
||||
if err = json.Unmarshal(respBody, &result); err != nil {
|
||||
log.Printf("json.Unmarshal: %e")
|
||||
return
|
||||
}
|
||||
|
||||
if !result.Data.RevocationStatus {
|
||||
atomic.AddInt32(&res, 1)
|
||||
}
|
||||
}()
|
||||
|
||||
wg.Wait()
|
||||
|
@ -339,7 +422,7 @@ func LegacyOAuth(db *sql.DB, bearer string, hash [64]byte,
|
|||
user User
|
||||
)
|
||||
query := database.
|
||||
Select(context.TODO(), []string{
|
||||
Select(r.Context(), []string{
|
||||
`ot.expires`,
|
||||
`ot.scopes`,
|
||||
`u.id`, `u.username`,
|
||||
|
|
Loading…
Reference in New Issue