tarakan-client/internal/api/device_auth.go
Maxfield Luke 58b29a7f84
Some checks failed
CI and releases / Test and vet (push) Failing after 1s
CI and releases / Build release binaries (push) Has been skipped
CI and releases / Publish GitHub release (push) Has been skipped
Initial commit on Forgejo
Fresh repository history for elektrine/tarakan-client hosted at
https://git.elektrine.com/elektrine/tarakan-client.
2026-07-29 04:56:36 -04:00

65 lines
2 KiB
Go

package api
import (
"context"
"errors"
"net/http"
"time"
)
var (
ErrAuthorizationPending = errors.New("browser authorization is still pending")
ErrAccessDenied = errors.New("browser authorization was denied")
ErrDeviceCodeExpired = errors.New("browser authorization expired")
)
type DeviceAuthorization struct {
DeviceCode string `json:"device_code"`
UserCode string `json:"user_code"`
VerificationURI string `json:"verification_uri"`
VerificationURIComplete string `json:"verification_uri_complete"`
ExpiresIn int64 `json:"expires_in"`
Interval int64 `json:"interval"`
}
type DeviceCredential struct {
Token string `json:"token"`
TokenType string `json:"token_type"`
ExpiresAt time.Time `json:"expires_at"`
Scopes []string `json:"scopes"`
}
func (c *Client) StartDeviceAuthorization(ctx context.Context, clientName string) (DeviceAuthorization, error) {
var authorization DeviceAuthorization
err := c.do(ctx, http.MethodPost, "/api/client-auth/start", map[string]string{
"client_name": clientName,
}, &authorization)
return authorization, err
}
func (c *Client) ExchangeDeviceAuthorization(ctx context.Context, deviceCode string) (DeviceCredential, error) {
var credential DeviceCredential
err := c.do(ctx, http.MethodPost, "/api/client-auth/exchange", map[string]string{
"device_code": deviceCode,
}, &credential)
if err == nil {
return credential, nil
}
var apiErr *APIError
if errors.As(err, &apiErr) {
switch apiErr.Message {
case "authorization_pending":
return DeviceCredential{}, ErrAuthorizationPending
case "access_denied":
return DeviceCredential{}, ErrAccessDenied
case "expired_token":
return DeviceCredential{}, ErrDeviceCodeExpired
}
}
return DeviceCredential{}, err
}
// RevokeCurrentCredential revokes the bearer token used by this client.
func (c *Client) RevokeCurrentCredential(ctx context.Context) error {
return c.do(ctx, http.MethodDelete, "/api/client-auth/session", nil, nil)
}