diff options
| -rw-r--r-- | exports/exports.go | 8 | ||||
| -rw-r--r-- | internal/fsm.go | 2 | ||||
| -rw-r--r-- | internal/oauth.go | 13 | ||||
| -rw-r--r-- | internal/server.go | 4 | ||||
| -rw-r--r-- | state.go | 17 | ||||
| -rw-r--r-- | state_test.go | 13 | ||||
| -rw-r--r-- | wrappers/python/eduvpncommon/__init__.py | 1 | ||||
| -rw-r--r-- | wrappers/python/eduvpncommon/main.py | 8 |
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 @@ -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() |
