diff --git a/cmd/config.go b/cmd/config.go index 6f9ddbc..75068a5 100644 --- a/cmd/config.go +++ b/cmd/config.go @@ -2,9 +2,10 @@ package cmd import ( opaal "davidallendj/opaal/internal" - "davidallendj/opaal/internal/util" "fmt" + "github.com/davidallendj/go-utils/util" + "github.com/spf13/cobra" ) diff --git a/cmd/root.go b/cmd/root.go index 156b29c..c1fb355 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -2,10 +2,10 @@ package cmd import ( opaal "davidallendj/opaal/internal" - "davidallendj/opaal/internal/util" "fmt" "os" + "github.com/davidallendj/go-utils/util" "github.com/spf13/cobra" ) diff --git a/config.yaml b/config.yaml new file mode 100755 index 0000000..992ac3b --- /dev/null +++ b/config.yaml @@ -0,0 +1,27 @@ +server: + host: 127.0.0.1 + port: 3333 +client: + id: 7527e7b4-c96a-4df0-8fc5-00fde18bb65d + secret: gto_cc5uvpb5lsdczkwnbarvwmbpv5kcjwg7nhbc75zt65yrfh2ldenq + redirect-uris: + - "http://127.0.0.1:3333/oidc/callback" +oidc: + issuer: "http://git.towk.local:3000/" +urls: + #identities: http://127.0.0.1:4434/admin/identities + trusted-issuers: http://127.0.0.1:4445/admin/trust/grants/jwt-bearer/issuers + access-token: http://127.0.0.1:4444/oauth2/token + server-config: http://git.towk.local:3000/.well-known/openid-configuration + jwks_uri: http://git.towk.local:3000/login/oauth/keys + login: http://127.0.0.1:4433/self-service/login/api + login-flow-id: http://127.0.0.1:4433/self-service/login/flows?id={id} +state: "" +response-type: code +decode-id-token: true +decode-access-token: true +run-once: true +scope: +- openid +- profile +- email diff --git a/go.mod b/go.mod index e459e10..f9921a3 100644 --- a/go.mod +++ b/go.mod @@ -3,9 +3,9 @@ module davidallendj/opaal go 1.22.0 require ( + github.com/davidallendj/go-utils v0.0.0-20240228023108-a3401c328af8 github.com/go-chi/chi v1.5.5 github.com/go-chi/chi/v5 v5.0.12 - github.com/golang-jwt/jwt v3.2.2+incompatible github.com/lestrrat-go/jwx v1.2.28 github.com/spf13/cobra v1.8.0 golang.org/x/net v0.10.0 @@ -15,6 +15,7 @@ require ( require ( github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect github.com/goccy/go-json v0.10.2 // indirect + github.com/golang-jwt/jwt v3.2.2+incompatible // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/lestrrat-go/backoff/v2 v2.0.8 // indirect github.com/lestrrat-go/blackmagic v1.0.2 // indirect diff --git a/go.sum b/go.sum index d7a787d..2ae2491 100644 --- a/go.sum +++ b/go.sum @@ -2,6 +2,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davidallendj/go-utils v0.0.0-20240228023108-a3401c328af8 h1:2TS/l1tLIJ5Qwh3owCM9kxvnGC186dZK9FllgmlDTXo= +github.com/davidallendj/go-utils v0.0.0-20240228023108-a3401c328af8/go.mod h1:dOlDYHzYfiz3Skh133YHRm9IiKxBdkMkvXip54057x8= github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= diff --git a/internal/client.go b/internal/client.go index d08d352..355207e 100644 --- a/internal/client.go +++ b/internal/client.go @@ -3,7 +3,6 @@ package opaal import ( "bytes" "davidallendj/opaal/internal/oidc" - "davidallendj/opaal/internal/util" "encoding/json" "fmt" "io" @@ -13,6 +12,7 @@ import ( "strings" "time" + "github.com/davidallendj/go-utils/util" "golang.org/x/net/publicsuffix" ) @@ -41,7 +41,7 @@ func (client *Client) IsFlowInitiated() bool { func (client *Client) BuildAuthorizationUrl(authEndpoint string, state string, responseType string, scope []string) string { return authEndpoint + "?" + "client_id=" + client.Id + - "&redirect_uri=" + util.URLEscape(strings.Join(client.RedirectUris, ",")) + + "&redirect_uri=" + url.QueryEscape(strings.Join(client.RedirectUris, ",")) + "&response_type=" + responseType + "&state=" + state + "&scope=" + strings.Join(scope, "+") + @@ -148,7 +148,7 @@ func (client *Client) FetchTokenFromAuthenticationServer(code string, remoteUrl func (client *Client) FetchTokenFromAuthorizationServer(remoteUrl string, jwt string, scope []string) ([]byte, error) { // hydra endpoint: /oauth/token - data := "grant_type=" + util.URLEscape("urn:ietf:params:oauth:grant-type:jwt-bearer") + + data := "grant_type=" + url.QueryEscape("urn:ietf:params:oauth:grant-type:jwt-bearer") + "&client_id=" + client.Id + "&client_secret=" + client.Secret + "&scope=" + strings.Join(scope, "+") + @@ -211,6 +211,12 @@ func (client *Client) AddTrustedIssuer(remoteUrl string, idp *oidc.IdentityProvi return io.ReadAll(res.Body) } +func (client *Client) AuthorizeClient(authorizeUrl string) ([]byte, error) { + bytes := []byte{} + + return bytes, nil +} + func (client *Client) RegisterOAuthClient(registerUrl string, audience []string) ([]byte, error) { // hydra endpoint: POST /clients audience = util.QuoteArrayStrings(audience) diff --git a/internal/config.go b/internal/config.go index b9c3946..d887ed9 100644 --- a/internal/config.go +++ b/internal/config.go @@ -2,11 +2,12 @@ package opaal import ( "davidallendj/opaal/internal/oidc" - "davidallendj/opaal/internal/util" "log" "os" "path/filepath" + goutil "github.com/davidallendj/go-utils/util" + "gopkg.in/yaml.v2" ) @@ -23,11 +24,12 @@ type Config struct { DecodeIdToken bool `yaml:"decode-id-token"` DecodeAccessToken bool `yaml:"decode-access-token"` RunOnce bool `yaml:"run-once"` + GrantType string `yaml:"grant-type"` } func NewConfig() Config { return Config{ - Version: util.GetCommit(), + Version: goutil.GetCommit(), Server: Server{ Host: "127.0.0.1", Port: 3333, @@ -38,7 +40,7 @@ func NewConfig() Config { RedirectUris: []string{""}, }, IdentityProvider: *oidc.NewIdentityProvider(), - State: util.RandomString(20), + State: goutil.RandomString(20), ResponseType: "code", Scope: []string{"openid", "profile", "email"}, ActionUrls: ActionUrls{ @@ -51,6 +53,7 @@ func NewConfig() Config { DecodeIdToken: false, DecodeAccessToken: false, RunOnce: true, + GrantType: "authorization_code", } } diff --git a/internal/login.go b/internal/login.go index 0beb0c5..048b262 100644 --- a/internal/login.go +++ b/internal/login.go @@ -2,13 +2,14 @@ package opaal import ( "davidallendj/opaal/internal/oidc" - "davidallendj/opaal/internal/util" "encoding/json" "errors" "fmt" "net/http" "reflect" "time" + + "github.com/davidallendj/go-utils/util" ) func Login(config *Config) error { diff --git a/internal/util/util.go b/internal/util/util.go deleted file mode 100644 index 4ba8156..0000000 --- a/internal/util/util.go +++ /dev/null @@ -1,109 +0,0 @@ -package util - -import ( - "encoding/base64" - "math/rand" - "net/url" - "os" - "os/exec" - "runtime" - "strings" - - "github.com/golang-jwt/jwt" -) - -func RandomString(n int) string { - const letterBytes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" - const ( - letterIdxBits = 6 // 6 bits to represent a letter index - letterIdxMask = 1<= 0; { - if remain == 0 { - cache, remain = rand.Int63(), letterIdxMax - } - if idx := int(cache & letterIdxMask); idx < len(letterBytes) { - b[i] = letterBytes[idx] - i-- - } - cache >>= letterIdxBits - remain-- - } - - return string(b) -} - -func URLEscape(s string) string { - return url.QueryEscape(s) -} - -func EncodeBase64(s string) string { - return base64.StdEncoding.EncodeToString([]byte(s)) -} - -func DecodeJwt(encoded string) ([][]byte, error) { - // split the string into 3 segments and decode - segments := strings.Split(encoded, ".") - decoded := [][]byte{} - for _, segment := range segments { - bytes, _ := jwt.DecodeSegment(segment) - decoded = append(decoded, bytes) - } - return decoded, nil -} - -func PathExists(path string) (bool, error) { - _, err := os.Stat(path) - if err == nil { - return true, nil - } - if os.IsNotExist(err) { - return false, nil - } - return false, err -} - -// https://stackoverflow.com/questions/39320371/how-start-web-server-to-open-page-in-browser-in-golang -// open opens the specified URL in the default browser of the user. -func OpenUrl(url string) error { - var cmd string - var args []string - - switch runtime.GOOS { - case "windows": - cmd = "cmd" - args = []string{"/c", "start"} - case "darwin": - cmd = "open" - default: // "linux", "freebsd", "openbsd", "netbsd" - cmd = "xdg-open" - } - args = append(args, url) - return exec.Command(cmd, args...).Start() -} - -func GetCommit() string { - bytes, err := exec.Command("git", "rev --parse HEAD").Output() - if err != nil { - return "" - } - return string(bytes) -} - -func Tokenize(s string) map[string]any { - tokens := make(map[string]any) - - // find token enclosed in curly brackets - - return tokens -} - -func QuoteArrayStrings(arr []string) []string { - for i, v := range arr { - arr[i] = "\"" + v + "\"" - } - return arr -}