Browse Source

Added more oauth2 code

Toby Chui 6 months ago
parent
commit
1c3f8511a0
4 changed files with 56 additions and 14 deletions
  1. 37 10
      mod/auth/sso/oauth2.go
  2. 1 0
      mod/auth/sso/oauth_test.go
  3. 17 4
      mod/auth/sso/sso.go
  4. 1 0
      mod/dynamicproxy/Server.go

+ 37 - 10
mod/auth/sso/oauth2.go

@@ -4,7 +4,6 @@ import (
 	"context"
 	_ "embed"
 	"encoding/json"
-	"fmt"
 	"log"
 	"net/http"
 	"net/url"
@@ -20,6 +19,10 @@ import (
 	"imuslab.com/zoraxy/mod/utils"
 )
 
+const (
+	SSO_SESSION_NAME = "ZoraxySSO"
+)
+
 type OAuth2Server struct {
 	srv    *server.Server //oAuth server instance
 	config *SSOConfig
@@ -37,7 +40,7 @@ func NewOAuth2Server(config *SSOConfig, parent *SSOHandler) (*OAuth2Server, erro
 	manager := manage.NewDefaultManager()
 	manager.SetAuthorizeCodeTokenCfg(manage.DefaultAuthorizeCodeTokenCfg)
 	// token store
-	manager.MustTokenStorage(store.NewMemoryTokenStore())
+	manager.MustTokenStorage(store.NewFileTokenStore("./conf/sso.db"))
 	// generate jwt access token
 	manager.MapAccessGenerate(generates.NewAccessGenerate())
 
@@ -48,6 +51,7 @@ func NewOAuth2Server(config *SSOConfig, parent *SSOHandler) (*OAuth2Server, erro
 		Secret: "verysecurepassword",
 		Domain: "localhost:9094",
 	})
+	//TODO: LOAD THIS DYNAMICALLY FROM DATABASE
 	manager.MapClientStorage(clientStore)
 
 	thisServer := OAuth2Server{
@@ -66,15 +70,16 @@ func NewOAuth2Server(config *SSOConfig, parent *SSOHandler) (*OAuth2Server, erro
 	srv.SetResponseErrorHandler(func(re *errors.Response) {
 		log.Println("Response Error:", re.Error.Error())
 	})
+	srv.SetAccessTokenExpHandler(thisServer.ExpireHandler)
 	thisServer.srv = srv
 	return &thisServer, nil
 }
 
 // Password handler, validate if the given username and password are correct
 func (oas *OAuth2Server) PasswordAuthorizationHandler(ctx context.Context, clientID, username, password string) (userID string, err error) {
-	fmt.Println(username, password)
-	if username == "alanyeung" && password == "password" {
-		userID = "alanyeung"
+	//TODO: LOAD THIS DYNAMICALLY FROM DATABASE
+	if username == "test" && password == "test" {
+		userID = "test"
 	}
 	return
 }
@@ -86,7 +91,7 @@ func (oas *OAuth2Server) UserAuthorizeHandler(w http.ResponseWriter, r *http.Req
 		return
 	}
 
-	uid, ok := store.Get("ZoraxySSO")
+	uid, ok := store.Get(SSO_SESSION_NAME)
 	if !ok {
 		if r.Form == nil {
 			r.ParseForm()
@@ -101,11 +106,30 @@ func (oas *OAuth2Server) UserAuthorizeHandler(w http.ResponseWriter, r *http.Req
 	}
 
 	userID = uid.(string)
-	store.Delete("ZoraxySSO")
+	store.Delete(SSO_SESSION_NAME)
 	store.Save()
 	return
 }
 
+// AccessTokenExpHandler, set the SSO session length default value
+func (oas *OAuth2Server) ExpireHandler(w http.ResponseWriter, r *http.Request) (exp time.Duration, err error) {
+	requestHostname := r.Host
+	if requestHostname == "" {
+		//Use default value
+		return time.Hour, nil
+	}
+
+	//Get the Registered App Config from parent
+	appConfig, ok := oas.parent.Apps[requestHostname]
+	if !ok {
+		//Use default value
+		return time.Hour, nil
+	}
+
+	//Use the app's session length
+	return time.Second * time.Duration(appConfig.SessionDuration), nil
+}
+
 /* SSO Web Server Toggle Functions */
 func (oas *OAuth2Server) RegisterOauthEndpoints(primaryMux *http.ServeMux) {
 	primaryMux.HandleFunc("/oauth2/login", oas.loginHandler)
@@ -193,7 +217,7 @@ func (oas *OAuth2Server) loginHandler(w http.ResponseWriter, r *http.Request) {
 			return
 		}
 
-		store.Set("ZoraxySSO", r.Form.Get("username"))
+		store.Set(SSO_SESSION_NAME, r.Form.Get("username"))
 		store.Save()
 
 		w.Header().Set("Location", "/oauth2/auth")
@@ -211,12 +235,15 @@ func (oas *OAuth2Server) authHandler(w http.ResponseWriter, r *http.Request) {
 		return
 	}
 
-	if _, ok := store.Get("ZoraxySSO"); !ok {
+	if _, ok := store.Get(SSO_SESSION_NAME); !ok {
 		w.Header().Set("Location", "/oauth2/login")
 		w.WriteHeader(http.StatusFound)
 		return
 	}
+	//User logged in. Check if this user have previously authorized the app
+
+	//TODO: Check if the user have previously authorized the app
 
-	//User logged in. Show authentication confirm page
+	//User have not authorized the app. Show the authorization page
 	w.Write(authHtml)
 }

+ 1 - 0
mod/auth/sso/oauth_test.go

@@ -0,0 +1 @@
+package sso

+ 17 - 4
mod/auth/sso/sso.go

@@ -23,18 +23,31 @@ import (
 var staticFiles embed.FS //Static files for the SSO portal
 
 type SSOConfig struct {
-	SystemUUID       string //System UUID, should be passed in from main scope
-	AuthURL          string //Authentication subdomain URL, e.g. auth.example.com
-	PortalServerPort int    //SSO portal server port
-	Database         *database.Database
+	SystemUUID       string             //System UUID, should be passed in from main scope
+	AuthURL          string             //Authentication subdomain URL, e.g. auth.example.com
+	PortalServerPort int                //SSO portal server port
+	Database         *database.Database //System master key-value database
 	Logger           *logger.Logger
 }
+
+// RegisteredUpstreamApp is a structure that contains the information of an
+// upstream app that is registered with the SSO server
+type RegisteredUpstreamApp struct {
+	ID              string
+	Secret          string
+	Domain          []string
+	Scopes          []string
+	SessionDuration int //in seconds, default to 1 hour
+}
+
+// SSOHandler is the main SSO handler structure
 type SSOHandler struct {
 	cookieStore     *sessions.CookieStore
 	ssoPortalServer *http.Server
 	ssoPortalMux    *http.ServeMux
 	Oauth2Server    *OAuth2Server
 	Config          *SSOConfig
+	Apps            map[string]RegisteredUpstreamApp
 }
 
 // Create a new Zoraxy SSO handler

+ 1 - 0
mod/dynamicproxy/Server.go

@@ -21,6 +21,7 @@ import (
 			- Blacklist
 			- Whitelist
 		- Rate Limitor
+		- SSO Auth (wip)
 		- Basic Auth
 		- Vitrual Directory Proxy
 		- Subdomain Proxy