summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjwijenbergh <jeroenwijenbergh@protonmail.com>2022-04-26 15:43:35 +0200
committerjwijenbergh <jeroenwijenbergh@protonmail.com>2022-04-26 15:43:35 +0200
commit75aa163ccf407e9690f9ea0e548f8fed70073722 (patch)
treedd68386a24c8c479149d094bb209fb0a78071c06
parenta5d33f95ba68263e6c0ca758c5b854530332d9ae (diff)
OAuth: Add a Cancel method
-rw-r--r--exports/exports.go8
-rw-r--r--internal/fsm.go2
-rw-r--r--internal/oauth.go13
-rw-r--r--internal/server.go4
-rw-r--r--state.go17
-rw-r--r--state_test.go13
-rw-r--r--wrappers/python/eduvpncommon/__init__.py1
-rw-r--r--wrappers/python/eduvpncommon/main.py8
8 files changed, 59 insertions, 7 deletions
diff --git a/exports/exports.go b/exports/exports.go
index aa6f5b6..d81f1ce 100644
--- a/exports/exports.go
+++ b/exports/exports.go
@@ -53,6 +53,14 @@ func ErrorToString(error error) string {
return error.Error()
}
+//export CancelOAuth
+func CancelOAuth() (*C.char) {
+ state := eduvpn.GetVPNState()
+ cancelErr := state.CancelOAuth()
+ cancelErrString := ErrorToString(cancelErr)
+ return C.CString(cancelErrString)
+}
+
//export Connect
func Connect(url *C.char) (*C.char, *C.char) {
state := eduvpn.GetVPNState()
diff --git a/internal/fsm.go b/internal/fsm.go
index 5aa3f50..e848cae 100644
--- a/internal/fsm.go
+++ b/internal/fsm.go
@@ -106,7 +106,7 @@ func (fsm *FSM) Init(name string, callback func(string, string, string), logger
DEREGISTERED: {{NO_SERVER, "Client registers"}},
NO_SERVER: {{CHOSEN_SERVER, "User chooses a server"}},
CHOSEN_SERVER: {{AUTHENTICATED, "Found tokens in config"}, {OAUTH_STARTED, "No tokens found in config"}},
- OAUTH_STARTED: {{AUTHENTICATED, "User authorizes with browser"}},
+ OAUTH_STARTED: {{AUTHENTICATED, "User authorizes with browser"}, {CHOSEN_SERVER, "Cancel OAuth"}},
AUTHENTICATED: {{OAUTH_STARTED, "Re-authenticate with OAuth"}, {REQUEST_CONFIG, "Client requests a config"}},
REQUEST_CONFIG: {{ASK_PROFILE, "Multiple profiles found"}, {HAS_CONFIG, "Success, only one profile"}},
ASK_PROFILE: {{HAS_CONFIG, "User chooses profile and success"}},
diff --git a/internal/oauth.go b/internal/oauth.go
index 16edd1e..a49b492 100644
--- a/internal/oauth.go
+++ b/internal/oauth.go
@@ -271,6 +271,7 @@ func (oauth *OAuth) Finish() error {
return errors.New("invalid state to finish oauth")
}
tokenErr := oauth.getTokensWithCallback()
+
if tokenErr != nil {
return tokenErr
}
@@ -278,6 +279,11 @@ func (oauth *OAuth) Finish() error {
return nil
}
+func (oauth *OAuth) Cancel() {
+ oauth.Session.CallbackError = &OAuthCancelledCallbackError{}
+ oauth.Session.Server.Shutdown(oauth.Session.Context)
+}
+
func (oauth *OAuth) Login(name string, authorizationURL string, tokenURL string) error {
authInitializeErr := oauth.start(name, authorizationURL, tokenURL)
@@ -320,6 +326,13 @@ func (oauth *OAuth) NeedsRelogin() bool {
return true
}
+type OAuthCancelledCallbackError struct {
+}
+
+func (e *OAuthCancelledCallbackError) Error() string {
+ return fmt.Sprintf("Client cancelled OAuth")
+}
+
type OAuthGenStateUnableError struct {
Err error
}
diff --git a/internal/server.go b/internal/server.go
index 48a0e85..aa21a97 100644
--- a/internal/server.go
+++ b/internal/server.go
@@ -33,6 +33,10 @@ func (servers *Servers) GetCurrentServer() (*Server, error) {
return server, nil
}
+func (server *Server) CancelOAuth() {
+ server.OAuth.Cancel()
+}
+
func (server *Server) Init(url string, fsm *FSM, logger *FileLogger) error {
server.BaseURL = url
server.FSM = fsm
diff --git a/state.go b/state.go
index 29f8a1e..8fbc7d2 100644
--- a/state.go
+++ b/state.go
@@ -81,6 +81,20 @@ func (state *VPNState) Deregister() error {
return nil
}
+func (state *VPNState) CancelOAuth() error {
+ if !state.FSM.InState(internal.OAUTH_STARTED) {
+ return errors.New("cannot cancel oauth, oauth not started")
+ }
+
+ server, serverErr := state.Servers.GetCurrentServer()
+
+ if serverErr != nil {
+ return serverErr
+ }
+ server.CancelOAuth()
+ return nil
+}
+
func (state *VPNState) Connect(url string) (string, error) {
if state.FSM.InState(internal.DEREGISTERED) {
return "", errors.New("app not registered")
@@ -99,6 +113,9 @@ func (state *VPNState) Connect(url string) (string, error) {
loginErr := server.Login()
if loginErr != nil {
+ // We are possibly in oauth started
+ // So go to chosen server
+ state.FSM.GoTransition(internal.CHOSEN_SERVER)
return "", loginErr
}
} else { // OAuth was valid, ensure we are in the authenticated state
diff --git a/state_test.go b/state_test.go
index 9527528..9578307 100644
--- a/state_test.go
+++ b/state_test.go
@@ -34,19 +34,20 @@ func runCommand(t *testing.T, errBuffer *strings.Builder, name string, args ...s
return cmd.Wait()
}
-func loginOAuthSelenium(t *testing.T, url string) {
+func loginOAuthSelenium(t *testing.T, url string, state *VPNState) {
// We could use the go selenium library
// But it does not support the latest selenium v4 just yet
var errBuffer strings.Builder
err := runCommand(t, &errBuffer, "python3", "selenium_eduvpn.py", url)
if err != nil {
t.Errorf("Login OAuth with selenium script failed with error %v and stderr %s", err, errBuffer.String())
+ state.CancelOAuth()
}
}
-func stateCallback(t *testing.T, oldState string, newState string, data string) {
+func stateCallback(t *testing.T, oldState string, newState string, data string, state *VPNState) {
if newState == "OAuth_Started" {
- go loginOAuthSelenium(t, data)
+ loginOAuthSelenium(t, data, state)
}
}
@@ -55,7 +56,7 @@ func Test_server(t *testing.T) {
state := &VPNState{}
state.Register("org.eduvpn.app.linux", "configstest", func(old string, new string, data string) {
- stateCallback(t, old, new, data)
+ stateCallback(t, old, new, data, state)
}, false)
_, configErr := state.Connect(serverURI)
@@ -126,7 +127,7 @@ func Test_token_expired(t *testing.T) {
state := &VPNState{}
state.Register("org.eduvpn.app.linux", "configsexpired", func(old string, new string, data string) {
- stateCallback(t, old, new, data)
+ stateCallback(t, old, new, data, state)
}, false)
_, configErr := state.Connect(serverURI)
@@ -170,7 +171,7 @@ func Test_token_invalid(t *testing.T) {
state := &VPNState{}
state.Register("org.eduvpn.app.linux", "configsinvalid", func(old string, new string, data string) {
- stateCallback(t, old, new, data)
+ stateCallback(t, old, new, data, state)
}, false)
_, configErr := state.Connect(serverURI)
diff --git a/wrappers/python/eduvpncommon/__init__.py b/wrappers/python/eduvpncommon/__init__.py
index 67e0d3b..e0fe0d0 100644
--- a/wrappers/python/eduvpncommon/__init__.py
+++ b/wrappers/python/eduvpncommon/__init__.py
@@ -38,6 +38,7 @@ lib.Deregister.argtypes, lib.Deregister.restype = [], None
lib.Register.argtypes, lib.Register.restype = [c_char_p, c_char_p, VPNStateChange, c_int], c_void_p
lib.GetOrganizationsList.argtypes, lib.GetOrganizationsList.restype = [], DataError
lib.GetServersList.argtypes, lib.GetServersList.restype = [], DataError
+lib.CancelOAuth.argtypes, lib.CancelOAuth.restype = [], c_void_p
lib.SetProfileID.argtypes, lib.SetProfileID.restype = [c_char_p], c_void_p
# We have to use c_void_p instead of c_char_p to free it properly
# See https://stackoverflow.com/questions/13445568/python-ctypes-how-to-free-memory-getting-invalid-pointer-error
diff --git a/wrappers/python/eduvpncommon/main.py b/wrappers/python/eduvpncommon/main.py
index da8b186..eae7014 100644
--- a/wrappers/python/eduvpncommon/main.py
+++ b/wrappers/python/eduvpncommon/main.py
@@ -18,6 +18,11 @@ def Register(name, config_directory, state_callback, debug):
err_string = GetPtrString(ptr_err)
return err_string
+def CancelOAuth():
+ ptr_err = lib.CancelOAuth()
+ err_string = GetPtrString(ptr_err)
+ return err_string
+
def Deregister():
lib.Deregister()
@@ -58,6 +63,9 @@ class EduVPN(object):
self.config_directory = config_directory
register_callback(self)
+ def cancel_oauth(self) -> str:
+ return CancelOAuth()
+
def deregister(self):
Deregister()