diff --git a/docs/api/wallet-rpc.yaml b/docs/api/wallet-rpc.yaml index 56cf11d..fe5fb0c 100644 --- a/docs/api/wallet-rpc.yaml +++ b/docs/api/wallet-rpc.yaml @@ -105,12 +105,17 @@ paths: $ref: '#/components/responses/404-NotFound' /session: get: + security: + - {} + - bearerAuth: [] summary: get current status of backend operationId: session - description: get whether a wallet is loaded and whether coinjoin/maker are happening. + description: get whether a wallet is loaded and whether coinjoin/maker are happening. if an auth token is provided, which is optional, it will be validated. responses: '200': $ref: "#/components/responses/Session-200-OK" + '401': + $ref: '#/components/responses/401-Unauthorized' '404': $ref: '#/components/responses/404-NotFound' /wallet/all: diff --git a/jmclient/jmclient/wallet_rpc.py b/jmclient/jmclient/wallet_rpc.py index 3efe09a..71916bd 100644 --- a/jmclient/jmclient/wallet_rpc.py +++ b/jmclient/jmclient/wallet_rpc.py @@ -342,6 +342,11 @@ class JMWalletDaemon(Service): jlog.warn("Invalid cookie: " + str( request_cookie) + ", request rejected.") raise NotAuthorized() + + def check_cookie_if_present(self, request): + auth_header = request.getHeader('Authorization') + if auth_header is not None: + self.check_cookie(request) def set_token(self, wallet_name): """ This function creates a new JWT token and sets it as our @@ -502,6 +507,10 @@ class JMWalletDaemon(Service): to the client what the current status of the wallet and services is. TODO: add more data to send to client. """ + #validate auth header if provided + #this lets caller know if cookie is invalid or outdated + self.check_cookie_if_present(request) + #if no wallet loaded then clear frontend session info #when no wallet status is false session = not self.cookie==None diff --git a/jmclient/test/test_wallet_rpc.py b/jmclient/test/test_wallet_rpc.py index 7ed31c1..5173e07 100644 --- a/jmclient/test/test_wallet_rpc.py +++ b/jmclient/test/test_wallet_rpc.py @@ -158,6 +158,27 @@ class TrialTestWRPC_DisplayWallet(WalletRPCTestBase, unittest.TestCase): yield handler(body, response.code) return True + @defer.inlineCallbacks + def do_session_request(self, agent, addr, handler=None, token=None): + """ A `None` value for handler is reserved for the case + where we expect an Unauthorized request because we provided a token, + but it is not valid. + For other cases, provide the url prefix before `/session' as addr, + and we expect a 200 if token is valid *or* token is None, but contents + are to be checked by provided response handler callback. + """ + if handler is None: + assert token is not None + handler = self.unauthorized_session_request_handler + yield self.do_request(agent, b"GET", (addr+"/session").encode(), + None, handler, token) + + def authorized_session_request_handler(self, response, code): + assert code == 200 + + def unauthorized_session_request_handler(self, response, code): + assert code == 401 + @defer.inlineCallbacks def test_create_list_lock_unlock(self): """ A batch of tests in sequence here, @@ -195,6 +216,13 @@ class TrialTestWRPC_DisplayWallet(WalletRPCTestBase, unittest.TestCase): yield self.do_request(agent, b"POST", addr, body, self.process_create_wallet_response) + # 1a. Session request with valid token; should succeed + yield self.do_session_request(agent, root, + self.authorized_session_request_handler, token=self.jwt_token) + # 1b. Session request without token, even though one is active; should succeed + yield self.do_session_request(agent, root, + self.authorized_session_request_handler) + # 2. now *lock* addr = root + "/wallet/" + wfn1 + "/lock" addr = addr.encode() @@ -202,6 +230,13 @@ class TrialTestWRPC_DisplayWallet(WalletRPCTestBase, unittest.TestCase): yield self.do_request(agent, b"GET", addr, None, self.process_lock_response, token=self.jwt_token) + # 2a. Session request with now invalid token; should fail + yield self.do_session_request(agent, root, + self.unauthorized_session_request_handler, token=self.jwt_token) + # 2b. Session request without token, should still succeed. + yield self.do_session_request(agent, root, + self.authorized_session_request_handler) + # 3. Create this secondary wallet (so we can test re-unlock) addr = root + "/wallet/create" addr = addr.encode()