-
Notifications
You must be signed in to change notification settings - Fork 261
Auth0 integration_V2 #703
Auth0 integration_V2 #703
Changes from all commits
85f5785
d289150
b6029ff
9b75668
eb09550
4c75879
93a94df
c378e9e
eb6574b
ef1b06b
96fad7b
c325878
65499e7
0584f93
939863e
5002d86
1d182dd
157408c
4120425
8b3b33a
3b55fbd
9f721e0
aecf3e4
26fdb7d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -39,6 +39,8 @@ import ( | |
"github.com/stellar/kelp/support/prefs" | ||
"github.com/stellar/kelp/support/sdk" | ||
"github.com/stellar/kelp/support/utils" | ||
"github.com/stellar/kelp/support/guiconfig" | ||
"github.com/stellar/go/support/config" | ||
) | ||
|
||
const kelpAssetsPath = "/assets" | ||
|
@@ -72,6 +74,15 @@ type serverInputOptions struct { | |
enableKaas *bool | ||
tlsCertFile *string | ||
tlsKeyFile *string | ||
guiConfigPath *string | ||
} | ||
|
||
// checks for required flag on CLI | ||
func requiredFlags(flag string) { | ||
e := serverCmd.MarkFlagRequired(flag) | ||
if e != nil { | ||
panic(e) | ||
} | ||
} | ||
|
||
// String is the stringer method impl. | ||
|
@@ -80,6 +91,19 @@ func (o serverInputOptions) String() string { | |
*o.port, *o.dev, *o.devAPIPort, *o.horizonTestnetURI, *o.horizonPubnetURI, *o.noHeaders, *o.verbose, *o.noElectron, *o.disablePubnet, *o.enableKaas) | ||
} | ||
|
||
// function for reading custom config file and returning config struct with intilized value | ||
func readGUIConfig(options serverInputOptions) guiconfig.GUIConfig { | ||
var guiConfigInFunc guiconfig.GUIConfig | ||
e := config.Read(*options.guiConfigPath, &guiConfigInFunc) | ||
utils.CheckConfigError(guiConfigInFunc, e, *options.guiConfigPath) | ||
if e != nil { | ||
panic(fmt.Errorf("could not read GUI config file '%s': %s", *options.guiConfigPath, e)) | ||
} | ||
return guiConfigInFunc | ||
} | ||
// customConfigVar Variable with its equivalent struct #used to inject config values to jwt config var and to configure route | ||
var auth0ConfigVar guiconfig.GUIConfig | ||
|
||
func init() { | ||
options := serverInputOptions{} | ||
options.port = serverCmd.Flags().Uint16P("port", "p", 8000, "port on which to serve HTTP") | ||
|
@@ -95,6 +119,9 @@ func init() { | |
options.enableKaas = serverCmd.Flags().Bool("enable-kaas", false, "enable kelp-as-a-service (KaaS) mode, which does not bring up browser or electron") | ||
options.tlsCertFile = serverCmd.Flags().String("tls-cert-file", "", "path to TLS certificate file") | ||
options.tlsKeyFile = serverCmd.Flags().String("tls-key-file", "", "path to TLS key file") | ||
options.guiConfigPath = serverCmd.Flags().StringP("guiconfig", "c", "", "(required) gui-config for auth0 and other basic config file path") | ||
|
||
requiredFlags("guiconfig") | ||
|
||
serverCmd.Run = func(ccmd *cobra.Command, args []string) { | ||
isLocalMode := env == envDev | ||
|
@@ -143,6 +170,10 @@ func init() { | |
|
||
log.Printf("initialized server with cli flag inputs: %s", options) | ||
|
||
//calliing readGUIConfig func and then inject values into JWT_middleware customconfigvar | ||
auth0ConfigVar = readGUIConfig(options) | ||
backend.Auth0ConfigVarJWT = auth0ConfigVar | ||
|
||
if runtime.GOOS == "windows" { | ||
if !*options.noElectron { | ||
log.Printf("input options had specified noElectron=false for windows, but electron is not supported on windows yet. force setting noElectron=true for windows.\n") | ||
|
@@ -382,6 +413,7 @@ func init() { | |
*options.noHeaders, | ||
quit, | ||
metricsTracker, | ||
auth0ConfigVar, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. thanks for fitting into the existing serverMetadata pattern! 🎉 |
||
) | ||
if e != nil { | ||
panic(e) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# Sample UI config file for the kelp bot | ||
|
||
# uncomment the AUTH0 section below to enable | ||
# [AUTH0] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
# AUTH0_ENABLED=false | ||
# #auth0 domain | ||
# DOMAIN= #"domain_goes_here" #example "dev-*******.eu.auth0.com" | ||
# #auth0 clientID | ||
# CLIENT_ID= #"Client_id_goes_here" #examples "7I47ob2************XKF29hY5" | ||
# #auth0 audience | ||
# AUDIENCE= #"Audience/Identifier goes_here" |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,6 +16,7 @@ import ( | |
"github.com/stellar/go/clients/horizonclient" | ||
"github.com/stellar/kelp/plugins" | ||
"github.com/stellar/kelp/support/kelpos" | ||
"github.com/stellar/kelp/support/guiconfig" | ||
) | ||
|
||
// UserData is the json data passed in to represent a user | ||
|
@@ -59,6 +60,7 @@ type APIServer struct { | |
kelpErrorsByUserLock *sync.Mutex | ||
|
||
cachedOptionsMetadata metadata | ||
guiConfig guiconfig.GUIConfig | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
} | ||
|
||
// MakeAPIServer is a factory method | ||
|
@@ -76,6 +78,7 @@ func MakeAPIServer( | |
noHeaders bool, | ||
quitFn func(), | ||
metricsTracker *plugins.MetricsTracker, | ||
guiConfig guiconfig.GUIConfig, | ||
) (*APIServer, error) { | ||
kelpBinPath := kos.GetBinDir().Join(filepath.Base(os.Args[0])) | ||
|
||
|
@@ -102,6 +105,7 @@ func MakeAPIServer( | |
metricsTracker: metricsTracker, | ||
kelpErrorsByUser: map[string]kelpErrorDataForUser{}, | ||
kelpErrorsByUserLock: &sync.Mutex{}, | ||
guiConfig: guiConfig, | ||
}, nil | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
package backend | ||
|
||
import ( | ||
"encoding/json" | ||
"errors" | ||
"net/http" | ||
"fmt" | ||
|
||
jwtmiddleware "github.com/auth0/go-jwt-middleware" | ||
"github.com/form3tech-oss/jwt-go" | ||
"github.com/stellar/kelp/support/guiconfig" | ||
) | ||
|
||
type Response struct { | ||
Message string `json:"message"` | ||
} | ||
|
||
type Jwks struct { | ||
Keys []JSONWebKeys `json:"keys"` | ||
} | ||
|
||
type JSONWebKeys struct { | ||
Kty string `json:"kty"` | ||
Kid string `json:"kid"` | ||
Use string `json:"use"` | ||
N string `json:"n"` | ||
E string `json:"e"` | ||
X5c []string `json:"x5c"` | ||
} | ||
|
||
var Auth0ConfigVarJWT guiconfig.GUIConfig | ||
|
||
var JWTMiddlewareVar = jwtmiddleware.New(jwtmiddleware.Options{ | ||
ValidationKeyGetter: func(token *jwt.Token) (interface{}, error) { | ||
// Verify 'iss' claim | ||
iss := "https://" + Auth0ConfigVarJWT.Auth0Config.Domain + "/" | ||
checkIss := token.Claims.(jwt.MapClaims).VerifyIssuer(iss, false) | ||
if !checkIss { | ||
return token, errors.New("Invalid issuer.") | ||
} | ||
|
||
// Verify 'aud' claim | ||
aud := Auth0ConfigVarJWT.Auth0Config.Audience | ||
checkAud := token.Claims.(jwt.MapClaims).VerifyAudience(aud, false) | ||
if !checkAud { | ||
return token, errors.New("Invalid audience.") | ||
} | ||
|
||
cert, err := getPemCert(token) | ||
if err != nil { | ||
return nil, fmt.Errorf("error when getting PEM certificate: %s", err) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
} | ||
|
||
result, _ := jwt.ParseRSAPublicKeyFromPEM([]byte(cert)) | ||
return result, nil | ||
}, | ||
SigningMethod: jwt.SigningMethodRS256, | ||
}) | ||
|
||
func getPemCert(token *jwt.Token) (string, error) { | ||
cert := "" | ||
resp, err := http.Get("https://" + Auth0ConfigVarJWT.Auth0Config.Domain + "/.well-known/jwks.json") | ||
|
||
if err != nil { | ||
return cert, err | ||
} | ||
defer resp.Body.Close() | ||
|
||
var jwks = Jwks{} | ||
err = json.NewDecoder(resp.Body).Decode(&jwks) | ||
|
||
if err != nil { | ||
return cert, err | ||
} | ||
|
||
for k, _ := range jwks.Keys { | ||
if token.Header["kid"] == jwks.Keys[k].Kid { | ||
cert = "-----BEGIN CERTIFICATE-----\n" + jwks.Keys[k].X5c[0] + "\n-----END CERTIFICATE-----" | ||
} | ||
} | ||
|
||
if cert == "" { | ||
err := errors.New("Unable to find appropriate key.") | ||
return cert, err | ||
} | ||
|
||
return cert, nil | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,22 +18,27 @@ func SetRoutes(r *chi.Mux, s *APIServer) { | |
r.Get("/serverMetadata", http.HandlerFunc(s.serverMetadata)) | ||
r.Get("/newSecretKey", http.HandlerFunc(s.newSecretKey)) | ||
r.Get("/optionsMetadata", http.HandlerFunc(s.optionsMetadata)) | ||
var router chi.Router = r | ||
if s.guiConfig.Auth0Config != nil && s.guiConfig.Auth0Config.Auth0Enabled { | ||
// setting the router to use the JWT middleware to handle auth0 style JWT tokens | ||
router = r.With(JWTMiddlewareVar.Handler) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. much better, thank you!! 💯 🎉 |
||
} | ||
|
||
r.Post("/listBots", http.HandlerFunc(s.listBots)) | ||
r.Post("/genBotName", http.HandlerFunc(s.generateBotName)) | ||
r.Post("/getNewBotConfig", http.HandlerFunc(s.getNewBotConfig)) | ||
r.Post("/autogenerate", http.HandlerFunc(s.autogenerateBot)) | ||
r.Post("/fetchKelpErrors", http.HandlerFunc(s.fetchKelpErrors)) | ||
r.Post("/removeKelpErrors", http.HandlerFunc(s.removeKelpErrors)) | ||
r.Post("/start", http.HandlerFunc(s.startBot)) | ||
r.Post("/stop", http.HandlerFunc(s.stopBot)) | ||
r.Post("/deleteBot", http.HandlerFunc(s.deleteBot)) | ||
r.Post("/getState", http.HandlerFunc(s.getBotState)) | ||
r.Post("/getBotInfo", http.HandlerFunc(s.getBotInfo)) | ||
r.Post("/getBotConfig", http.HandlerFunc(s.getBotConfig)) | ||
r.Post("/fetchPrice", http.HandlerFunc(s.fetchPrice)) | ||
r.Post("/upsertBotConfig", http.HandlerFunc(s.upsertBotConfig)) | ||
r.Post("/sendMetricEvent", http.HandlerFunc(s.sendMetricEvent)) | ||
router.Post("/listBots", http.HandlerFunc(s.listBots)) | ||
router.Post("/genBotName", http.HandlerFunc(s.generateBotName)) | ||
router.Post("/getNewBotConfig", http.HandlerFunc(s.getNewBotConfig)) | ||
router.Post("/autogenerate", http.HandlerFunc(s.autogenerateBot)) | ||
router.Post("/fetchKelpErrors", http.HandlerFunc(s.fetchKelpErrors)) | ||
router.Post("/removeKelpErrors", http.HandlerFunc(s.removeKelpErrors)) | ||
router.Post("/start", http.HandlerFunc(s.startBot)) | ||
router.Post("/stop", http.HandlerFunc(s.stopBot)) | ||
router.Post("/deleteBot", http.HandlerFunc(s.deleteBot)) | ||
router.Post("/getState", http.HandlerFunc(s.getBotState)) | ||
router.Post("/getBotInfo", http.HandlerFunc(s.getBotInfo)) | ||
router.Post("/getBotConfig", http.HandlerFunc(s.getBotConfig)) | ||
router.Post("/fetchPrice", http.HandlerFunc(s.fetchPrice)) | ||
router.Post("/upsertBotConfig", http.HandlerFunc(s.upsertBotConfig)) | ||
router.Post("/sendMetricEvent", http.HandlerFunc(s.sendMetricEvent)) | ||
}) | ||
r.Get("/ping", http.HandlerFunc(s.ping)) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,18 +4,21 @@ import ( | |
"encoding/json" | ||
"fmt" | ||
"net/http" | ||
"github.com/stellar/kelp/support/guiconfig" | ||
) | ||
|
||
// ServerMetadataResponse is the response from the /serverMetadata endpoint | ||
type ServerMetadataResponse struct { | ||
DisablePubnet bool `json:"disable_pubnet"` | ||
EnableKaas bool `json:"enable_kaas"` | ||
GuiConfig guiconfig.GUIConfig `json:"guiconfig"` | ||
} | ||
|
||
func (s *APIServer) serverMetadata(w http.ResponseWriter, r *http.Request) { | ||
metadata := ServerMetadataResponse{ | ||
DisablePubnet: s.disablePubnet, | ||
EnableKaas: s.enableKaas, | ||
GuiConfig: s.guiConfig, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. perfect! 👍 |
||
} | ||
|
||
b, e := json.Marshal(metadata) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍 thanks!