this repo has no description

Merge pull request #4 from haileyok/hailey/cleanup

reorganize some things

authored by hailey.at and committed by GitHub f780d371 b8674747

Changed files
+61 -50
cmd
helpers
internal
helpers
+6 -6
README.md
··· 59 59 return err 60 60 } 61 61 62 - k, err := oauth.ParseJWKFromBytes(b) 62 + k, err := helpers.ParseJWKFromBytes(b) 63 63 if err != nil { 64 64 return err 65 65 } ··· 69 69 return err 70 70 } 71 71 72 - return e.JSON(200, oauth.CreateJwksResponseObject(pubKey)) 72 + return e.JSON(200, helpers.CreateJwksResponseObject(pubKey)) 73 73 } 74 74 ``` 75 75 ··· 90 90 return err 91 91 } 92 92 93 - k, err := oauth.ParseJWKFromBytes(b) 93 + k, err := helpers.ParseJWKFromBytes(b) 94 94 if err != nil { 95 95 return err 96 96 } 97 97 98 - cli, err := oauth.NewClient(oauth.ClientArgs{ 98 + cli, err := helpers.NewClient(oauth.ClientArgs{ 99 99 ClientJwk: k, 100 100 ClientId: clientId, 101 101 RedirectUri: callbackUrl, ··· 147 147 You'll need to create a private DPoP JWK for the user before directing them to their PDS to authenticate. You'll need to store this in a later step, and you will need to pass it along inside the PAR request, so go ahead and marshal it as well. 148 148 149 149 ```go 150 - k, err := oauth.GenerateKey(nil) 150 + k, err := helpers.GenerateKey(nil) 151 151 if err != nil { 152 152 return err 153 153 } ··· 268 268 oauthSession, err := s.getOauthSession(e.Request().Context(), did) 269 269 270 270 // Parse the user's JWK to pass into arguments 271 - privateJwk, err := oauth.ParseJWKFromBytes([]byte(oauthSession.DpopPrivateJwk)) 271 + privateJwk, err := helpers.ParseJWKFromBytes([]byte(oauthSession.DpopPrivateJwk)) 272 272 if err != nil { 273 273 return nil, false, err 274 274 }
+2 -2
cmd/helper/main.go
··· 4 4 "encoding/json" 5 5 "os" 6 6 7 - oauth "github.com/haileyok/atproto-oauth-golang" 7 + oauth_helpers "github.com/haileyok/atproto-oauth-golang/helpers" 8 8 "github.com/urfave/cli/v2" 9 9 ) 10 10 ··· 33 33 inputPrefix := cmd.String("prefix") 34 34 prefix = &inputPrefix 35 35 } 36 - key, err := oauth.GenerateKey(prefix) 36 + key, err := oauth_helpers.GenerateKey(prefix) 37 37 if err != nil { 38 38 return err 39 39 }
cmd/web_server_demo/client_test

This is a binary file and will not be displayed.

+3 -3
cmd/web_server_demo/handle_auth.go
··· 9 9 10 10 "github.com/bluesky-social/indigo/atproto/syntax" 11 11 "github.com/gorilla/sessions" 12 - oauth "github.com/haileyok/atproto-oauth-golang" 12 + oauth_helpers "github.com/haileyok/atproto-oauth-golang/helpers" 13 13 "github.com/labstack/echo-contrib/session" 14 14 "github.com/labstack/echo/v4" 15 15 "gorm.io/gorm/clause" ··· 71 71 return err 72 72 } 73 73 74 - dpopPrivateKey, err := oauth.GenerateKey(nil) 74 + dpopPrivateKey, err := oauth_helpers.GenerateKey(nil) 75 75 if err != nil { 76 76 return err 77 77 } ··· 159 159 return fmt.Errorf("incoming iss did not match authserver iss") 160 160 } 161 161 162 - jwk, err := oauth.ParseJWKFromBytes([]byte(oauthRequest.DpopPrivateJwk)) 162 + jwk, err := oauth_helpers.ParseJWKFromBytes([]byte(oauthRequest.DpopPrivateJwk)) 163 163 if err != nil { 164 164 return err 165 165 }
+4 -3
cmd/web_server_demo/main.go
··· 11 11 12 12 "github.com/gorilla/sessions" 13 13 oauth "github.com/haileyok/atproto-oauth-golang" 14 + oauth_helpers "github.com/haileyok/atproto-oauth-golang/helpers" 14 15 _ "github.com/joho/godotenv/autoload" 15 16 "github.com/labstack/echo-contrib/session" 16 17 "github.com/labstack/echo/v4" ··· 51 52 db *gorm.DB 52 53 oauthClient *oauth.Client 53 54 xrpcCli *oauth.XrpcClient 54 - jwksResponse *oauth.JwksResponseObject 55 + jwksResponse *oauth_helpers.JwksResponseObject 55 56 } 56 57 57 58 type TemplateRenderer struct { ··· 100 101 return nil, err 101 102 } 102 103 103 - k, err := oauth.ParseJWKFromBytes(b) 104 + k, err := oauth_helpers.ParseJWKFromBytes(b) 104 105 if err != nil { 105 106 return nil, err 106 107 } ··· 145 146 db: db, 146 147 oauthClient: c, 147 148 xrpcCli: xrpcCli, 148 - jwksResponse: oauth.CreateJwksResponseObject(pubKey), 149 + jwksResponse: oauth_helpers.CreateJwksResponseObject(pubKey), 149 150 }, nil 150 151 } 151 152
+3 -2
cmd/web_server_demo/user.go
··· 6 6 "time" 7 7 8 8 oauth "github.com/haileyok/atproto-oauth-golang" 9 + oauth_helpers "github.com/haileyok/atproto-oauth-golang/helpers" 9 10 "github.com/labstack/echo-contrib/session" 10 11 "github.com/labstack/echo/v4" 11 12 ) ··· 21 22 } 22 23 23 24 if oauthSession.Expiration.Sub(time.Now()) <= 5*time.Minute { 24 - privateJwk, err := oauth.ParseJWKFromBytes([]byte(oauthSession.DpopPrivateJwk)) 25 + privateJwk, err := oauth_helpers.ParseJWKFromBytes([]byte(oauthSession.DpopPrivateJwk)) 25 26 if err != nil { 26 27 return nil, err 27 28 } ··· 59 60 60 61 oauthSession, err := s.getOauthSession(e.Request().Context(), did) 61 62 62 - privateJwk, err := oauth.ParseJWKFromBytes([]byte(oauthSession.DpopPrivateJwk)) 63 + privateJwk, err := oauth_helpers.ParseJWKFromBytes([]byte(oauthSession.DpopPrivateJwk)) 63 64 if err != nil { 64 65 return nil, false, err 65 66 }
+4 -23
generic.go helpers/generic.go
··· 1 - package oauth 1 + package helpers 2 2 3 3 import ( 4 4 "crypto/ecdsa" 5 5 "crypto/elliptic" 6 6 "crypto/rand" 7 - "crypto/sha256" 8 - "encoding/base64" 9 - "encoding/hex" 10 7 "fmt" 11 8 "net/url" 12 9 "time" ··· 39 36 return key, nil 40 37 } 41 38 42 - func isSafeAndParsed(ustr string) (*url.URL, error) { 39 + func IsUrlSafeAndParsed(ustr string) (*url.URL, error) { 43 40 u, err := url.Parse(ustr) 44 41 if err != nil { 45 42 return nil, err ··· 64 61 return u, nil 65 62 } 66 63 67 - func getPrivateKey(key jwk.Key) (*ecdsa.PrivateKey, error) { 64 + func GetPrivateKey(key jwk.Key) (*ecdsa.PrivateKey, error) { 68 65 var pkey ecdsa.PrivateKey 69 66 if err := key.Raw(&pkey); err != nil { 70 67 return nil, err ··· 73 70 return &pkey, nil 74 71 } 75 72 76 - func getPublicKey(key jwk.Key) (*ecdsa.PublicKey, error) { 73 + func GetPublicKey(key jwk.Key) (*ecdsa.PublicKey, error) { 77 74 var pkey ecdsa.PublicKey 78 75 if err := key.Raw(&pkey); err != nil { 79 76 return nil, err ··· 95 92 func ParseJWKFromBytes(b []byte) (jwk.Key, error) { 96 93 return jwk.ParseKey(b) 97 94 } 98 - 99 - func generateToken(len int) (string, error) { 100 - b := make([]byte, len) 101 - if _, err := rand.Read(b); err != nil { 102 - return "", err 103 - } 104 - 105 - return hex.EncodeToString(b), nil 106 - } 107 - 108 - func generateCodeChallenge(pkceVerifier string) string { 109 - h := sha256.New() 110 - h.Write([]byte(pkceVerifier)) 111 - hash := h.Sum(nil) 112 - return base64.RawURLEncoding.EncodeToString(hash) 113 - }
+24
internal/helpers/generic.go
··· 1 + package helpers 2 + 3 + import ( 4 + "crypto/rand" 5 + "crypto/sha256" 6 + "encoding/base64" 7 + "encoding/hex" 8 + ) 9 + 10 + func GenerateToken(len int) (string, error) { 11 + b := make([]byte, len) 12 + if _, err := rand.Read(b); err != nil { 13 + return "", err 14 + } 15 + 16 + return hex.EncodeToString(b), nil 17 + } 18 + 19 + func GenerateCodeChallenge(pkceVerifier string) string { 20 + h := sha256.New() 21 + h.Write([]byte(pkceVerifier)) 22 + hash := h.Sum(nil) 23 + return base64.RawURLEncoding.EncodeToString(hash) 24 + }
+9 -7
oauth.go
··· 13 13 14 14 "github.com/golang-jwt/jwt/v5" 15 15 "github.com/google/uuid" 16 + "github.com/haileyok/atproto-oauth-golang/helpers" 17 + internal_helpers "github.com/haileyok/atproto-oauth-golang/internal/helpers" 16 18 "github.com/lestrrat-go/jwx/v2/jwk" 17 19 ) 18 20 ··· 46 48 } 47 49 } 48 50 49 - clientPkey, err := getPrivateKey(args.ClientJwk) 51 + clientPkey, err := helpers.GetPrivateKey(args.ClientJwk) 50 52 if err != nil { 51 53 return nil, fmt.Errorf("could not load private key from provided client jwk: %w", err) 52 54 } ··· 63 65 } 64 66 65 67 func (c *Client) ResolvePdsAuthServer(ctx context.Context, ustr string) (string, error) { 66 - u, err := isSafeAndParsed(ustr) 68 + u, err := helpers.IsUrlSafeAndParsed(ustr) 67 69 if err != nil { 68 70 return "", err 69 71 } ··· 104 106 } 105 107 106 108 func (c *Client) FetchAuthServerMetadata(ctx context.Context, ustr string) (*OauthAuthorizationMetadata, error) { 107 - u, err := isSafeAndParsed(ustr) 109 + u, err := helpers.IsUrlSafeAndParsed(ustr) 108 110 if err != nil { 109 111 return nil, err 110 112 } ··· 219 221 220 222 parUrl := authServerMeta.PushedAuthorizationRequestEndpoint 221 223 222 - state, err := generateToken(10) 224 + state, err := internal_helpers.GenerateToken(10) 223 225 if err != nil { 224 226 return nil, fmt.Errorf("could not generate state token: %w", err) 225 227 } 226 228 227 - pkceVerifier, err := generateToken(48) 229 + pkceVerifier, err := internal_helpers.GenerateToken(48) 228 230 if err != nil { 229 231 return nil, fmt.Errorf("could not generate pkce verifier: %w", err) 230 232 } 231 233 232 - codeChallenge := generateCodeChallenge(pkceVerifier) 234 + codeChallenge := internal_helpers.GenerateCodeChallenge(pkceVerifier) 233 235 codeChallengeMethod := "S256" 234 236 235 237 clientAssertion, err := c.ClientAssertionJwt(authServerUrl) ··· 259 261 params.Set("login_hint", loginHint) 260 262 } 261 263 262 - _, err = isSafeAndParsed(parUrl) 264 + _, err = helpers.IsUrlSafeAndParsed(parUrl) 263 265 if err != nil { 264 266 return nil, err 265 267 }
+4 -3
oauth_test.go
··· 8 8 "os" 9 9 "testing" 10 10 11 + "github.com/haileyok/atproto-oauth-golang/helpers" 11 12 _ "github.com/joho/godotenv/autoload" 12 13 "github.com/stretchr/testify/assert" 13 14 ) ··· 27 28 panic(err) 28 29 } 29 30 30 - k, err := ParseJWKFromBytes(b) 31 + k, err := helpers.ParseJWKFromBytes(b) 31 32 if err != nil { 32 33 panic(err) 33 34 } ··· 81 82 assert := assert.New(t) 82 83 83 84 prefix := "testing" 84 - _, err := GenerateKey(&prefix) 85 + _, err := helpers.GenerateKey(&prefix) 85 86 assert.NoError(err) 86 87 } 87 88 ··· 95 96 } 96 97 97 98 prefix := "testing" 98 - dpopPriv, err := GenerateKey(&prefix) 99 + dpopPriv, err := helpers.GenerateKey(&prefix) 99 100 if err != nil { 100 101 panic(err) 101 102 }
+2 -1
xrpc.go
··· 16 16 "github.com/carlmjohnson/versioninfo" 17 17 "github.com/golang-jwt/jwt/v5" 18 18 "github.com/google/uuid" 19 + "github.com/haileyok/atproto-oauth-golang/internal/helpers" 19 20 "github.com/lestrrat-go/jwx/v2/jwk" 20 21 ) 21 22 ··· 115 116 "jti": uuid.NewString(), 116 117 "htm": method, 117 118 "htu": url, 118 - "ath": generateCodeChallenge(accessToken), 119 + "ath": helpers.GenerateCodeChallenge(accessToken), 119 120 } 120 121 121 122 if nonce != "" {