this repo has no description

cleanup stuff

Changed files
+66 -89
cmd
client_test
+2 -2
cmd/client_test/main.go
···
httpd *http.Server
e *echo.Echo
db *gorm.DB
-
oauthClient *oauth.OauthClient
+
oauthClient *oauth.Client
xrpcCli *oauth.XrpcClient
jwksResponse *oauth.JwksResponseObject
}
···
return nil, err
}
-
c, err := oauth.NewOauthClient(oauth.OauthClientArgs{
+
c, err := oauth.NewClient(oauth.ClientArgs{
ClientJwk: k,
ClientId: serverMetadataUrl,
RedirectUri: serverCallbackUrl,
+2 -1
go.mod
···
require (
github.com/bluesky-social/indigo v0.0.0-20250301025210-a4e0cc37e188
+
github.com/carlmjohnson/versioninfo v0.22.5
github.com/golang-jwt/jwt/v5 v5.2.1
github.com/google/uuid v1.6.0
github.com/gorilla/sessions v1.4.0
···
github.com/samber/slog-echo v1.15.1
github.com/stretchr/testify v1.10.0
github.com/urfave/cli/v2 v2.27.5
+
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa
gorm.io/driver/sqlite v1.5.7
gorm.io/gorm v1.25.9
)
require (
-
github.com/carlmjohnson/versioninfo v0.22.5 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
+2
go.sum
···
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
+
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ=
+
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-11
helpers.go
···
-
package oauth
-
-
func tokenInSet(tok string, set []string) bool {
-
for _, setTok := range set {
-
if tok == setTok {
-
return true
-
}
-
}
-
-
return false
-
}
+16 -51
oauth.go
···
"github.com/lestrrat-go/jwx/v2/jwk"
)
-
type OauthClient struct {
+
type Client struct {
h *http.Client
clientPrivateKey *ecdsa.PrivateKey
clientKid string
···
redirectUri string
}
-
type OauthClientArgs struct {
+
type ClientArgs struct {
H *http.Client
ClientJwk jwk.Key
ClientId string
RedirectUri string
}
-
func NewOauthClient(args OauthClientArgs) (*OauthClient, error) {
+
func NewClient(args ClientArgs) (*Client, error) {
if args.ClientId == "" {
return nil, fmt.Errorf("no client id provided")
}
···
kid := args.ClientJwk.KeyID()
-
return &OauthClient{
+
return &Client{
h: args.H,
clientKid: kid,
clientPrivateKey: clientPkey,
···
}, nil
}
-
func (c *OauthClient) ResolvePDSAuthServer(ctx context.Context, ustr string) (string, error) {
+
func (c *Client) ResolvePDSAuthServer(ctx context.Context, ustr string) (string, error) {
u, err := isSafeAndParsed(ustr)
if err != nil {
return "", err
···
return resource.AuthorizationServers[0], nil
}
-
func (c *OauthClient) FetchAuthServerMetadata(
-
ctx context.Context,
-
ustr string,
-
) (*OauthAuthorizationMetadata, error) {
+
func (c *Client) FetchAuthServerMetadata(ctx context.Context, ustr string) (*OauthAuthorizationMetadata, error) {
u, err := isSafeAndParsed(ustr)
if err != nil {
return nil, err
···
return &metadata, nil
}
-
func (c *OauthClient) ClientAssertionJwt(authServerUrl string) (string, error) {
+
func (c *Client) ClientAssertionJwt(authServerUrl string) (string, error) {
claims := jwt.MapClaims{
"iss": c.clientId,
"sub": c.clientId,
···
return tokenString, nil
}
-
func (c *OauthClient) AuthServerDpopJwt(method, url, nonce string, privateJwk jwk.Key) (string, error) {
+
func (c *Client) AuthServerDpopJwt(method, url, nonce string, privateJwk jwk.Key) (string, error) {
pubJwk, err := privateJwk.PublicKey()
if err != nil {
return "", err
···
return tokenString, nil
}
-
type SendParAuthResponse struct {
-
PkceVerifier string
-
State string
-
DpopAuthserverNonce string
-
Resp map[string]any
-
}
-
-
func (c *OauthClient) SendParAuthRequest(ctx context.Context, authServerUrl string, authServerMeta *OauthAuthorizationMetadata, loginHint, scope string, dpopPrivateKey jwk.Key) (*SendParAuthResponse, error) {
+
func (c *Client) SendParAuthRequest(ctx context.Context, authServerUrl string, authServerMeta *OauthAuthorizationMetadata, loginHint, scope string, dpopPrivateKey jwk.Key) (*SendParAuthResponse, error) {
if authServerMeta == nil {
return nil, fmt.Errorf("nil metadata provided")
}
···
if err := json.NewDecoder(resp2.Body).Decode(&rmap); err != nil {
return nil, err
}
-
-
fmt.Println(rmap)
}
return &SendParAuthResponse{
···
}, nil
}
-
type TokenResponse struct {
-
DpopAuthserverNonce string
-
Resp map[string]any
-
}
-
-
func (c *OauthClient) InitialTokenRequest(
+
func (c *Client) InitialTokenRequest(
ctx context.Context,
code,
appUrl,
···
}
defer resp.Body.Close()
-
// TODO: use nonce if needed, same as in par
-
var rmap map[string]any
if err := json.NewDecoder(resp.Body).Decode(&rmap); err != nil {
return nil, err
···
}, nil
}
-
type RefreshTokenArgs struct {
-
AuthserverUrl string
-
RefreshToken string
-
DpopPrivateJwk string
-
DpopAuthserverNonce string
-
}
-
-
func (c *OauthClient) RefreshTokenRequest(
-
ctx context.Context,
-
args RefreshTokenArgs,
-
appUrl string,
-
) (any, error) {
-
authserverMeta, err := c.FetchAuthServerMetadata(ctx, args.AuthserverUrl)
+
func (c *Client) RefreshTokenRequest(ctx context.Context, authserverUrl, refreshToken, dpopAuthserverNonce string, dpopPrivateJwk jwk.Key) (*TokenResponse, error) {
+
authserverMeta, err := c.FetchAuthServerMetadata(ctx, authserverUrl)
if err != nil {
return nil, err
}
-
clientAssertion, err := c.ClientAssertionJwt(args.AuthserverUrl)
+
clientAssertion, err := c.ClientAssertionJwt(authserverUrl)
if err != nil {
return nil, err
}
···
params := url.Values{
"client_id": {c.clientId},
"grant_type": {"refresh_token"},
-
"refresh_token": {args.RefreshToken},
+
"refresh_token": {refreshToken},
"client_assertion_type": {"urn:ietf:params:oauth:client-assertion-type:jwt-bearer"},
"client_assertion": {clientAssertion},
}
-
dpopPrivateJwk, err := parsePrivateJwkFromString(args.DpopPrivateJwk)
-
if err != nil {
-
return nil, err
-
}
-
dpopProof, err := c.AuthServerDpopJwt(
"POST",
authserverMeta.TokenEndpoint,
-
args.DpopAuthserverNonce,
+
dpopAuthserverNonce,
dpopPrivateJwk,
)
if err != nil {
···
}
return &TokenResponse{
-
DpopAuthserverNonce: args.DpopAuthserverNonce,
+
DpopAuthserverNonce: dpopAuthserverNonce,
Resp: rmap,
}, nil
}
+2 -2
oauth_test.go
···
pdsUrl = os.Getenv("OAUTH_TEST_PDS_URL")
)
-
func newTestOauthClient() *OauthClient {
+
func newTestOauthClient() *Client {
b, err := os.ReadFile("./jwks.json")
if err != nil {
panic(err)
···
panic(err)
}
-
c, err := NewOauthClient(OauthClientArgs{
+
c, err := NewClient(ClientArgs{
ClientJwk: k,
ClientId: serverMetadataUrl,
RedirectUri: serverCallbackUrl,
+42 -22
types.go
···
"encoding/json"
"fmt"
"net/url"
+
"slices"
)
+
+
type TokenResponse struct {
+
DpopAuthserverNonce string
+
Resp map[string]any
+
}
+
+
type RefreshTokenArgs struct {
+
AuthserverUrl string
+
RefreshToken string
+
DpopPrivateJwk string
+
DpopAuthserverNonce string
+
}
+
+
type SendParAuthResponse struct {
+
PkceVerifier string
+
State string
+
DpopAuthserverNonce string
+
Resp map[string]any
+
}
type OauthProtectedResource struct {
Resource string `json:"resource"`
···
ClientIDMetadataDocumentSupported bool `json:"client_id_metadata_document_supported"`
}
+
func (oam *OauthAuthorizationMetadata) UnmarshalJSON(b []byte) error {
+
type Tmp OauthAuthorizationMetadata
+
var tmp Tmp
+
+
if err := json.Unmarshal(b, &tmp); err != nil {
+
return err
+
}
+
+
*oam = OauthAuthorizationMetadata(tmp)
+
+
return nil
+
}
+
func (oam *OauthAuthorizationMetadata) Validate(fetch_url *url.URL) error {
if fetch_url == nil {
return fmt.Errorf("fetch_url was nil")
···
return fmt.Errorf("issuer url params are not empty")
}
-
if !tokenInSet("code", oam.ResponseTypesSupported) {
+
if !slices.Contains(oam.ResponseTypesSupported, "code") {
return fmt.Errorf("`code` is not in response_types_supported")
}
-
if !tokenInSet("authorization_code", oam.GrantTypesSupported) {
+
if !slices.Contains(oam.GrantTypesSupported, "authorization_code") {
return fmt.Errorf("`authorization_code` is not in grant_types_supported")
}
-
if !tokenInSet("refresh_token", oam.GrantTypesSupported) {
+
if !slices.Contains(oam.GrantTypesSupported, "refresh_token") {
return fmt.Errorf("`refresh_token` is not in grant_types_supported")
}
-
if !tokenInSet("S256", oam.CodeChallengeMethodsSupported) {
+
if !slices.Contains(oam.CodeChallengeMethodsSupported, "S256") {
return fmt.Errorf("`S256` is not in code_challenge_methods_supported")
}
-
if !tokenInSet("none", oam.TokenEndpointAuthMethodsSupported) {
+
if !slices.Contains(oam.TokenEndpointAuthMethodsSupported, "none") {
return fmt.Errorf("`none` is not in token_endpoint_auth_methods_supported")
}
-
if !tokenInSet("private_key_jwt", oam.TokenEndpointAuthMethodsSupported) {
+
if !slices.Contains(oam.TokenEndpointAuthMethodsSupported, "private_key_jwt") {
return fmt.Errorf("`private_key_jwt` is not in token_endpoint_auth_methods_supported")
}
-
if !tokenInSet("ES256", oam.TokenEndpointAuthSigningAlgValuesSupported) {
+
if !slices.Contains(oam.TokenEndpointAuthSigningAlgValuesSupported, "ES256") {
return fmt.Errorf("`ES256` is not in token_endpoint_auth_signing_alg_values_supported")
}
-
if !tokenInSet("atproto", oam.ScopesSupported) {
+
if !slices.Contains(oam.ScopesSupported, "atproto") {
return fmt.Errorf("`atproto` is not in scopes_supported")
}
···
return fmt.Errorf("require_pushed_authorization_requests is false")
}
-
if !tokenInSet("ES256", oam.DpopSigningAlgValuesSupported) {
+
if !slices.Contains(oam.DpopSigningAlgValuesSupported, "ES256") {
return fmt.Errorf("`ES256` is not in dpop_signing_alg_values_supported")
}
···
return nil
}
-
-
func (oam *OauthAuthorizationMetadata) UnmarshalJSON(b []byte) error {
-
type Tmp OauthAuthorizationMetadata
-
var tmp Tmp
-
-
if err := json.Unmarshal(b, &tmp); err != nil {
-
return err
-
}
-
-
*oam = OauthAuthorizationMetadata(tmp)
-
-
return nil
-
}