mirror of https://git.sr.ht/~sircmpwn/gql.sr.ht
Add OAuth client internal auth mechanism
This commit is contained in:
parent
5206db0eff
commit
646e9d90c4
|
@ -145,6 +145,65 @@ func authForUsername(ctx context.Context, username string) (*AuthContext, error)
|
|||
return &auth, nil
|
||||
}
|
||||
|
||||
func authForOAuthClient(ctx context.Context, clientUUID string) (*AuthContext, error) {
|
||||
var auth AuthContext
|
||||
if err := database.WithTx(ctx, &sql.TxOptions{
|
||||
Isolation: 0,
|
||||
ReadOnly: true,
|
||||
}, func(tx *sql.Tx) error {
|
||||
var (
|
||||
err error
|
||||
rows *sql.Rows
|
||||
)
|
||||
query := database.
|
||||
Select(ctx, []string{
|
||||
`u.id`, `u.username`,
|
||||
`u.created`, `u.updated`,
|
||||
`u.email`,
|
||||
`u.user_type`,
|
||||
`u.url`, `u.location`, `u.bio`,
|
||||
`u.suspension_notice`,
|
||||
}).
|
||||
From(`"oauth2_client" client`).
|
||||
Join(`"user" u ON u.id = client.owner_id`).
|
||||
Where(`client.client_uuid = ?`, clientUUID)
|
||||
if rows, err = query.RunWith(tx).Query(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
if !rows.Next() {
|
||||
if err := rows.Err(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return fmt.Errorf("Authenticating for unknown client ID %s", clientUUID)
|
||||
}
|
||||
if err := rows.Scan(&auth.UserID, &auth.Username, &auth.Created,
|
||||
&auth.Updated, &auth.Email, &auth.UserType, &auth.URL, &auth.Location,
|
||||
&auth.Bio, &auth.SuspensionNotice); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if rows.Next() {
|
||||
// TODO: Fetch user info from meta if necessary
|
||||
if err := rows.Err(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
panic(errors.New("Multiple matching user accounts; invariant broken"))
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if auth.UserType == USER_SUSPENDED {
|
||||
return nil, fmt.Errorf(
|
||||
"Account suspended with the following notice: %s\nContact support",
|
||||
auth.SuspensionNotice)
|
||||
}
|
||||
|
||||
return &auth, nil
|
||||
}
|
||||
|
||||
type AuthCookie struct {
|
||||
// The username of the authenticated user
|
||||
Name string `json:"name"`
|
||||
|
@ -185,6 +244,9 @@ type InternalAuth struct {
|
|||
|
||||
// An arbitrary identifier for this internal node, e.g. "us-east-3.git.sr.ht"
|
||||
NodeID string `json:"node_id"`
|
||||
|
||||
// Only used by specific meta.sr.ht routes
|
||||
OAuthClientUUID string `json:"oauth_client_id",omit-empty`
|
||||
}
|
||||
|
||||
func internalAuth(internalNet []*net.IPNet, payload []byte,
|
||||
|
@ -224,7 +286,12 @@ func internalAuth(internalNet []*net.IPNet, payload []byte,
|
|||
authError(w, "Invalid Authorization header", http.StatusForbidden)
|
||||
}
|
||||
|
||||
auth, err := authForUsername(r.Context(), internalAuth.Name)
|
||||
var auth *AuthContext
|
||||
if internalAuth.OAuthClientUUID != "" {
|
||||
auth, err = authForOAuthClient(r.Context(), internalAuth.OAuthClientUUID)
|
||||
} else {
|
||||
auth, err = authForUsername(r.Context(), internalAuth.Name)
|
||||
}
|
||||
if err != nil {
|
||||
authError(w, err.Error(), http.StatusForbidden)
|
||||
return
|
||||
|
@ -472,7 +539,7 @@ func OAuth2(token string, hash [64]byte, w http.ResponseWriter,
|
|||
|
||||
if ot.Grants != "" {
|
||||
auth.Access = make(map[string]string)
|
||||
for _, grant := range strings.Split(ot.Grants, ",") {
|
||||
for _, grant := range strings.Split(ot.Grants, " ") {
|
||||
var (
|
||||
service string
|
||||
scope string
|
||||
|
@ -480,7 +547,7 @@ func OAuth2(token string, hash [64]byte, w http.ResponseWriter,
|
|||
)
|
||||
parts := strings.Split(grant, "/")
|
||||
if len(parts) != 2 {
|
||||
panic(errors.New("OAuth grant without service/scope format"))
|
||||
panic(fmt.Errorf("OAuth grant '%s' without service/scope format", grant))
|
||||
}
|
||||
service = parts[0]
|
||||
parts = strings.Split(parts[1], ":")
|
||||
|
|
Loading…
Reference in New Issue