From 1777dd04769cb8f33d0f6580d12f42a2c3f0c81a Mon Sep 17 00:00:00 2001 From: Mateusz Bilski Date: Thu, 25 Jan 2024 12:03:50 +0100 Subject: [PATCH] Add support for tls callback (#99) --- cmd/oauth2.go | 2 ++ docs/examples.md | 20 ++++++++++++++++++++ internal/oauth2/oauth2.go | 24 ++++++++++++++++++++++-- 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/cmd/oauth2.go b/cmd/oauth2.go index 5730f06..17a94ac 100644 --- a/cmd/oauth2.go +++ b/cmd/oauth2.go @@ -72,6 +72,8 @@ func NewOAuth2Cmd(version, commit, date string) (cmd *OAuth2Cmd) { cmd.PersistentFlags().StringVar(&cconfig.TLSCert, "tls-cert", "", "path to tls cert pem file") cmd.PersistentFlags().StringVar(&cconfig.TLSKey, "tls-key", "", "path to tls key pem file") cmd.PersistentFlags().StringVar(&cconfig.TLSRootCA, "tls-root-ca", "", "path to tls root ca pem file") + cmd.PersistentFlags().StringVar(&cconfig.CallbackTLSCert, "callback-tls-cert", "", "path to callback tls cert pem file") + cmd.PersistentFlags().StringVar(&cconfig.CallbackTLSKey, "callback-tls-key", "", "path to callback tls key pem file") cmd.PersistentFlags().DurationVar(&cconfig.HTTPTimeout, "http-timeout", time.Minute, "http client timeout") cmd.PersistentFlags().DurationVar(&cconfig.BrowserTimeout, "browser-timeout", 10*time.Minute, "browser timeout") cmd.PersistentFlags().BoolVar(&cconfig.Insecure, "insecure", false, "allow insecure connections") diff --git a/docs/examples.md b/docs/examples.md index 00179ed..2155ee8 100644 --- a/docs/examples.md +++ b/docs/examples.md @@ -594,3 +594,23 @@ oauth2c https://oauth2c.us.authz.cloudentity.io/oauth2c/demo \ --rar '[{"type":"payment_initiation","locations":["https://example.com/payments"],"instructedAmount":{"currency":"EUR","amount":"123.50"},"creditorName":"Merchant A","creditorAccount":{"bic":"ABCIDEFFXXX","iban":"DE02100100109307118603"},"remittanceInformationUnstructured":"Ref Number Merchant"}]' ``` + +## Miscellaneous + +### Using HTTPs for Callback URL + +You can use `--callback-tls-cert` and `--callback-tls-key` flags to specify a +TLS certificate and key for the HTTPs callback redirect URL. + +```sh +oauth2c https://oauth2c.us.authz.cloudentity.io/oauth2c/demo \ + --client-id cauktionbud6q8ftlqq0 \ + --client-secret HCwQ5uuUWBRHd04ivjX5Kl0Rz8zxMOekeLtqzki0GPc \ + --response-types code \ + --response-mode query \ + --grant-type authorization_code \ + --auth-method client_secret_basic \ + --redirect-url https://localhost:9876/callback \ + --callback-tls-cert https://raw.githubusercontent.com/cloudentity/oauth2c/master/data/cert.pem \ + --callback-tls-key https://raw.githubusercontent.com/cloudentity/oauth2c/master/data/key.pem +``` diff --git a/internal/oauth2/oauth2.go b/internal/oauth2/oauth2.go index 0c8d300..2c8ed4d 100644 --- a/internal/oauth2/oauth2.go +++ b/internal/oauth2/oauth2.go @@ -2,6 +2,7 @@ package oauth2 import ( "context" + "crypto/tls" "encoding/base64" "encoding/json" "fmt" @@ -83,6 +84,8 @@ type ClientConfig struct { TLSCert string `validate:"omitempty,uri"` TLSKey string `validate:"omitempty,uri"` TLSRootCA string `validate:"omitempty,uri"` + CallbackTLSCert string `validate:"omitempty,uri"` + CallbackTLSKey string `validate:"omitempty,uri"` HTTPTimeout time.Duration BrowserTimeout time.Duration DPoP bool @@ -192,6 +195,7 @@ func WaitForCallback(clientConfig ClientConfig, serverConfig ServerConfig, hc *h var ( srv = http.Server{} redirectURL *url.URL + cert tls.Certificate done = make(chan struct{}) ) @@ -205,6 +209,16 @@ func WaitForCallback(clientConfig ClientConfig, serverConfig ServerConfig, hc *h redirectURL.Path = "/" } + if redirectURL.Scheme == "https" { + if cert, err = ReadKeyPair(clientConfig.CallbackTLSCert, clientConfig.CallbackTLSKey, hc); err != nil { + return request, errors.Wrapf(err, "failed to read callback tls key pair") + } + + srv.TLSConfig = &tls.Config{ + Certificates: []tls.Certificate{cert}, + } + } + http.HandleFunc(redirectURL.Path, func(w http.ResponseWriter, r *http.Request) { defer func() { time.AfterFunc(time.Second, func() { @@ -273,8 +287,14 @@ func WaitForCallback(clientConfig ClientConfig, serverConfig ServerConfig, hc *h go func() { defer close(done) - if serr := srv.ListenAndServe(); serr != http.ErrServerClosed { - err = serr + if redirectURL.Scheme == "https" { + if serr := srv.ListenAndServeTLS("", ""); serr != http.ErrServerClosed { + err = serr + } + } else { + if serr := srv.ListenAndServe(); serr != http.ErrServerClosed { + err = serr + } } }()