this repo has no description

reorganize some stuff

Changed files
+52 -41
cmd
helper
web_server_demo
helpers
internal
helpers
+2 -2
cmd/helper/main.go
··· 4 "encoding/json" 5 "os" 6 7 - oauth "github.com/haileyok/atproto-oauth-golang" 8 "github.com/urfave/cli/v2" 9 ) 10 ··· 33 inputPrefix := cmd.String("prefix") 34 prefix = &inputPrefix 35 } 36 - key, err := oauth.GenerateKey(prefix) 37 if err != nil { 38 return err 39 }
··· 4 "encoding/json" 5 "os" 6 7 + oauth_helpers "github.com/haileyok/atproto-oauth-golang/helpers" 8 "github.com/urfave/cli/v2" 9 ) 10 ··· 33 inputPrefix := cmd.String("prefix") 34 prefix = &inputPrefix 35 } 36 + key, err := oauth_helpers.GenerateKey(prefix) 37 if err != nil { 38 return err 39 }
cmd/web_server_demo/client_test

This is a binary file and will not be displayed.

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