Question
· Jul 23

JWT and CORS

Hi

I'm trying to use JWT authentication on a REST application in IRIS. The login API are correctly "injected" into the application. Login works fine with Postman and other REST clients, and subsequent calls to my REST API using the bearer token work fine (correctly authenticated). So far, so good.

The problem is that it doesn't work with Axios, so I can only test it, I cannot integrate it into my application. I found out the reason for this is that Axios is applying CORS whereas Postman and other REST test clients do not; that is, they don't send the "preflight" OPTIONS request, they send the POST request directly, and apparently IRIS is happy not having to deal with CORS in this case (in other words, it does not check the "allow origin" header, probably because there was no OPTIONS call?) Unfortunately the reverse is not true. Axios sends the OPTIONS preflight, to which IRIS responds with a 500 internal server error and no "Access-Control-Allow-Origin" response header. Axios still attempts to send the POST, but it is getting a NS_ERROR_DOM_BAD_URI error because it failed CORS validation.

As far as I can tell based on the CORS specification, Axios is right to apply CORS in this case, as this query does not (and CAN not) match the criteria for not using CORS (as described on MDN: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS). There does not seem to be a way to force Axios not to send the pre-flight when the situation is legitimate for CORS.

I have correctly configured the dispatch class to handle CORS; without JWT authentication, CORS is handled correctly. However the dispatch class is never invoked for the JWT authentication login API (not even OnPreHTTP). Apparently the CSP engine is handling the login API on its own and never delegates to the dispatch class. So as far as I can tell, there's no way to intercept the OPTIONS call to somehow ignore or accept it.

Is there a way to make this work in IRIS? Or conversely, does anyone knows of a (minimally invasive) way to force Axios to bypass the pre-flight for this specific call?

Thanks

Product version: IRIS 2023.1
$ZV: IRIS for Windows (x86-64) 2023.1.3 (Build 517U) Wed Jan 10 2024 13:36:58 EST
Discussion (9)2
Log in or sign up to continue

Please double check the version. 2023.1.3 should have the fix for this case
https://docs.intersystems.com/iris20231/csp/docbook/changes/index.html#C...

DP-423647: Process CORS request when handling requests with JWT Tokens

Category: CSP / ZEN
Platforms: All
Version: 2023.1.3

This change ensures that any request that handles JWT tokens also correctly process CORS requests, when applicable.

Though status 500 is strange by itself. Try enabling ISCLOG and see if any error is logged there

A few things revealed by the ISCLOG logging:

  • If "allowed authentication methods" is set to "password" only, the system seems to attempt to log in a user (during the OPTIONS interaction) and fails:

**CSPServer-2 2024-07-23 14:27:57.214638 ns=USER routine=%SYS.cspServer job=44424 tag=F20 sessionid=hgxRMlcT0W
[CSPLogin] Error: Reverting to prelogin security context. (822  )
 ¦0   6 USER …(e^AuditLoginFailure+87^%SYS.SECURITY^1%e^UsersCSPLogin+135^%SYS.SECURITY^1!e^CSPLogin+102^%SYS.cspServer^1$e^CSPDispatch+883^%SYS.cspServer^1$d^CSPDispatch+881^%SYS.cspServer^1%d^ProcessRequest+1^%CSP.Session.1^1!d^Request+683^%SYS.cspServer2^1 d^Request+25^%SYS.cspServer2^1%d^ProcessRequest+1^%CSP.Request.1^1d^css+21^%SYS.cspServer2^1 d^SuperServer+60^%SYS.SERVER^2d^^^0

**CSPServer-2 2024-07-23 14:27:57.2146733 ns=USER routine=%SYS.cspServer job=44424 tag=F20 sessionid=hgxRMlcT0W
[LoginFailed]Security error: 0   6 USER …(e^AuditLoginFailure+87^%SYS.SECURITY^1%e^UsersCSPLogin+135^%SYS.SECURITY^1!e^CSPLogin+102^%SYS.cspServer^1$e^CSPDispatch+883^%SYS.cspServer^1$d^CSPDispatch+881^%SYS.cspServer^1%d^ProcessRequest+1^%CSP.Session.1^1!d^Request+683^%SYS.cspServer2^1 d^Request+25^%SYS.cspServer2^1%d^ProcessRequest+1^%CSP.Request.1^1d^css+21^%SYS.cspServer2^1 d^SuperServer+60^%SYS.SERVER^2d^^^0

**CSPServer-2 2024-07-23 14:27:57.2147257 ns=USER routine=%SYS.cspServer job=44424 tag=F20 sessionid=hgxRMlcT0W
[LoginFailed]Redirecting to login page /csp/lspmanagement/login

**CSPServer-2 2024-07-23 14:27:57.2147994 ns=USER routine=%CSP.Request.1 job=44424 tag=F20 sessionid=hgxRMlcT0W
[UpdateURL] Looking up: //localhost/csp/lspmanagement/login path found: //localhost/csp/lspmanagement/ Appl= /csp/lspmanagement/    :%All/csp/lspmanagementUSER„LSP.REST.Management<„

Then gets a <PROTECT> error:

**CSPServer-2 2024-07-23 14:27:57.2153425 ns=USER routine=%SYS.cspServer job=44424 tag=F20 sessionid=hgxRMlcT0W
[callPage] Return Status
0  áŠ]<PROTECT>^%CSP.Login.1 ^|^^c:\intersystems\irishealth202312\mgr\user\|LSP.REST.Management.1 uUSER j^^%CSP.Login.1^0'e^ProcessCorsRequest+8^%CSP.Login.1^1e^zLogin+7^%CSP.REST.1^1$e^CSPDispatch+500^%SYS.cspServer^2$d^CSPDispatch+279^%SYS.cspServer^1%d^ProcessRequest+1^%CSP.Session.1^1!d^Request+683^%SYS.cspServer2^1 d^Request+25^%SYS.cspServer2^1%d^ProcessRequest+1^%CSP.Request.1^1d^css+21^%SYS.cspServer2^1 d^SuperServer+60^%SYS.SERVER^2d^^^0

**CSPServer-2 2024-07-23 14:27:57.2154258 ns=USER routine=%SYS.cspServer job=44424 tag=F20 sessionid=hgxRMlcT0W
[HandleError]: ERROR #5002: ObjectScript error: <PROTECT>^%CSP.Login.1 ^|^^c:\intersystems\irishealth202312\mgr\user\|LSP.REST.Management.1
0  áŠ]<PROTECT>^%CSP.Login.1 ^|^^c:\intersystems\irishealth202312\mgr\user\|LSP.REST.Management.1 uUSER j^^%CSP.Login.1^0'e^ProcessCorsRequest+8^%CSP.Login.1^1e^zLogin+7^%CSP.REST.1^1$e^CSPDispatch+500^%SYS.cspServer^2$d^CSPDispatch+279^%SYS.cspServer^1%d^ProcessRequest+1^%CSP.Session.1^1!d^Request+683^%SYS.cspServer2^1 d^Request+25^%SYS.cspServer2^1%d^ProcessRequest+1^%CSP.Request.1^1d^css+21^%SYS.cspServer2^1 d^SuperServer+60^%SYS.SERVER^2d^^^0

I would think that this attempt at login on the preflight call is incorrect?

  • If "Allowed Authentication Methods" is set to "unauthenticated" only, I don't see these errors in ISCLOG, but it still doesn't work as the engine does not process the "allow origin" header. And besides, this is not an acceptable situation as (based on my tests) my API is accessible without authentication in this case.
  • I see the same behavior if authentication is set to both unauthenticated and password. It appears to take the "path of least resistance", so no authentication errors in ISCLOG, but the result is the same ("allow origin" is not processed).

So I think we're looking at 2 issues here: the attempt at authentication of the OPTIONS call, which is probably not right? and the fact that the "allow origin" header is not processed.

BTW, how does that work anyway? Is any CORS origin supposed to be accepted for the login API?

I'll see if I can reproduce this on 2024.1, in case.

Well, it seems to have resolved the issue! Many thanks for your help Alexander, I appreciate it! 👍

I would say despite the "important note", it is not obvious this requirement applies to this situation, and it appears in a different part of the documentation from the one on JWT (https://docs.intersystems.com/iris20241/csp/docbook/Doc.View.cls?KEY=ROA...), so linking the 2 articles is not immediate. A note in the JWT article would be nice.