-
Notifications
You must be signed in to change notification settings - Fork 24
feat: Enables CORS and JWT configuration for WebApplications in CspApplication tag #973
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
feat: Enables CORS and JWT configuration for WebApplications in CspApplication tag #973
Conversation
|
(Unfortunately) CSPApplication has been deprecated in favor of WebApplication and CPFMerge, so we're really not looking to make any improvements to it. I'll let @isc-tleavitt and @isc-kiyer weigh in if they believe differently though. |
|
Hi @isc-dchui |
…corrected unittest classnames.
@AshokThangavel Thanks for the PR! Please remove any changes to CSPApplication. Since it is deprecated, we want to encourage moving to WebApplication. For tests added, please add them to WebApplication instead of CSPApplication. |
…d update CORS/JWT configuration
|
Hi @isc-kiyer |
isc-kiyer
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@AshokThangavel a few more comments (mostly regarding naming and removing redundancies)!
| JWTAuthEnabled="1" | ||
| JWTRefreshTokenTimeout="900" | ||
| CorsHeadersList="Access-Control-Allow-Origin, Access-Control-Allow-Methods, Access-Control-Allow-Headers, Access-Control-Allow-Credentials, Access-Control-Max-Age, Access-Control-Expose-Headers, Access-Control-Request-Method, Access-Control-Request-Headers" | ||
| PasswordAuthEnabled="1" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For WebApplication, these properties for auth are all encapsulated as part of AutheEnabled and not separate properties.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@isc-kiyer
Could you please provide an example of how the authentication settings are represented when they are encapsulated under the AuthEnabled attribute in the element?
A sample XML snippet would be very helpful.
Thank you!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Presumably this refers to how AutheEnabled is a bit string with these properties, e.g. AutheEnabled=32 means PasswordAuthEnabled=1
(see https://docs.intersystems.com/latest/csp/documatic/%25CSP.Documatic.cls?LIBRARY=%25SYS&CLASSNAME=Security.Applications#PROPERTY_AutheEnabled)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @isc-kiyer , @isc-dchui
Regarding the encapsulation of authentication properties within AutheEnabled. However, based on the class definition for Security.Applications in IRIS 2025.1, I believe these properties must remain discrete attributes within the <WebApplication> tag for the following reasons:
- Bitmask vs. Discrete Properties: The
AutheEnabledproperty is a bitmask specifically for legacy authentication mechanisms such as Kerberos (4), Password (32), and Unauthenticated (64). In contrast, JWT is implemented via standalone properties:JWTAuthEnabled,JWTRefreshTokenTimeout, andJWTAccessTokenTimeout. These are not bits within theAutheEnabledinteger and cannot be mathematically encapsulated into it. - CORS Configuration: Similarly, CORS settings (such as
CorsHeadersListandCorsAllowlist) are distinct string and boolean properties in theSecurity.Applicationsclass. They do not have a representation within the authentication bitmask. - Automated Handling by IPM: By including these as individual attributes in the
<WebApplication>tag, the%IPM.ResourceProcessor.WebApplicationclass can automatically parse, map, and persist these values during the installation process. This ensures that themodule.xmlremains the declarative source of truth for the application's security posture. - Consistency: Treating these as separate attributes aligns with how other non-bitmask properties (like
DispatchClassorCookiePath) are handled within the IPM schema.
<WebApplication
Url="/testcors"
CookiePath="/testcors"
AutheEnabled="32"
JWTAuthEnabled="1"
JWTAccessTokenTimeout="60"
JWTRefreshTokenTimeout="900"
CorsCredentialsAllowed="1"
CorsAllowlist="https://www.example.com"
CorsHeadersList="Access-Control-Allow-Origin, Access-Control-Allow-Methods, Access-Control-Allow-Headers"
PasswordAuthEnabled="1"
UnauthenticatedEnabled="0"
Recurse="1"
UseCookies="2" />
Could you check and suggest.
Thank you!
| CorsAllowlist="https://pm.intersystems.com" | ||
| CorsCredentialsAllowed="1" | ||
| CorsHeadersList="Access-Control-Allow-Origin, Access-Control-Allow-Methods, Access-Control-Allow-Headers, Access-Control-Allow-Credentials, Access-Control-Max-Age, Access-Control-Expose-Headers, Origin, Access-Control-Request-Method, Access-Control-Request-Headers" | ||
| PasswordAuthEnabled="1" Recurse="1" UnauthenticatedEnabled="0" UseCookies="2"/> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For WebApplication, these properties for auth are all encapsulated as part of AutheEnabled and not separate properties.
| JWTAccessTokenTimeout="60" | ||
| JWTAuthEnabled="1" | ||
| JWTRefreshTokenTimeout="900" | ||
| PasswordAuthEnabled="1" Recurse="1" UnauthenticatedEnabled="0" UseCookies="2"/> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For WebApplication, these properties for auth are all encapsulated as part of AutheEnabled and not separate properties.
| @@ -0,0 +1,72 @@ | |||
| /// This class validates that CORS headers and allowed origins are configured correctly, | |||
| /// and that JWT authentication is properly set up in the <b><WebApplication></b> configuration section. | |||
| Class Test.PM.Integration.ConfigCorsAndJWTInWebAppTest Extends Test.PM.Integration.Base | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test class captures the behavior so I don't think the unit tests are needed. Furthermore, in general, if unit testing a single feature, we prefer to keep tests in a single class and have multiple methods rather than splitting it across classes..
Lastly, I would name this Test.PM.Integration.ResourceProcessor.WebApplication so any other WebApplication related tests can be added here in future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the feedback.
I’ve made the changes based on your suggestions:
- Renamed the integration test class to
Test.PM.Integration.ResourceProcessor.WebApplication - Removed separate
unit test classessince the existing test class already captures the required behavior.
Thank you!
…and remove unit test classes
isc-dchui
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly stylistic nits
| { | ||
| set appList = "" | ||
| set pApps = $zstrip(pApps,"<>W") | ||
| if ( pApps = "*" ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: remove extra leading/trailing spaces inside the parentheses here and elsewhere
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed the space issue.
| } | ||
|
|
||
| Method SetCORSProps( | ||
| pApps As %String = "", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: remove the p- prefixes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed the p-Prefix from the parameters pApps and pCors and variables
| set appList = "" | ||
| set pApps = $zstrip(pApps,"<>W") | ||
| if ( pApps = "*" ) { | ||
| do ..GetCSPApplications(.appList) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: check status
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated the code!
| set originsList = $listfromstring(pAllowedOrigins,",") | ||
| set ptr = 0 | ||
| set sc = $$$OK | ||
| while $listnext(originsList, ptr, origin){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: missing space between ) and {
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed the space issue
| set ..TemplateResources("rest","PasswordAuthEnabled") = 1 | ||
| set ..TemplateResources("rest","UnauthenticatedEnabled") = 0 | ||
| set ..TemplateResources("rest","Recurse") = 1 | ||
| ;cors |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: use // for comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
modified to // for comments
src/cls/IPM/Main.cls
Outdated
| } | ||
| do ##class(%Library.Prompt).GetString(" Enter a comma separated list of web applications or * for all:", .tWebAppList) | ||
|
|
||
| #If $$$CacheVersionMajor>=2025 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: use if instead of #if
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated the code based on the comment
src/cls/IPM/Main.cls
Outdated
| do ##class(%Library.Prompt).GetYesNo("Configure Access-Control-Allow-Credentials:",.enableCors) | ||
| if enableCors { | ||
| do ##class(%Library.Prompt).GetString(" Enter a comma separated list of Allowed Headers:",.allowedHeaders,,32767,"comma seperated values e.g: Access-Control-Allow-Origin,Access-Control-Allow-Headers") | ||
| while (1){ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: missing space between ) and {
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed the space issue
| JWTAuthEnabled="1" | ||
| JWTRefreshTokenTimeout="900" | ||
| CorsHeadersList="Access-Control-Allow-Origin, Access-Control-Allow-Methods, Access-Control-Allow-Headers, Access-Control-Allow-Credentials, Access-Control-Max-Age, Access-Control-Expose-Headers, Access-Control-Request-Method, Access-Control-Request-Headers" | ||
| PasswordAuthEnabled="1" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Presumably this refers to how AutheEnabled is a bit string with these properties, e.g. AutheEnabled=32 means PasswordAuthEnabled=1
(see https://docs.intersystems.com/latest/csp/documatic/%25CSP.Documatic.cls?LIBRARY=%25SYS&CLASSNAME=Security.Applications#PROPERTY_AutheEnabled)
|
Also you need a changelog entry |
PR: Feature - Default CORS and JWT Configuration for Web Applications
This Pull Request enables default configuration settings for Cross-Origin Resource Sharing (CORS) and JSON Web Token (JWT) Authentication directly into the IPM
module.xml<WebApplication>resource definition. This enhancement enables the use of existing features through the package manager.Fixes #814
Summary of Feature Enhancements
This feature request introduces the following capabilities:
Support for loading CORS and JWT properties defined in the
<WebApplication>configuration sectionSupport for loading CORS and JWT properties generated through the IPM CLI (
Generate/gen) commandelement with the correct<CSPApplication><WebApplication>element.Key Features & Rationale
CorsAllowlist,CorsCredentialsAllowed,CorsHeadersListJWTAuthEnabled,JWTAccessTokenTimeout,JWTRefreshTokenTimeoutCombined Configuration Example
The following attributes are now included in the
<WebApplication>tag by default, ensuring immediate security compliance for the created web application (/testcors):Detailed Test Results
Extensive unit and integration testing was performed to validate the correct application of these settings. All tests passed successfully, confirming the configuration integrity and non-interference between the two security features.
1. Unit Test Results (CORS Configuration Verification)
Class:
Test.PM.Unit.WebAppCorsTest2. Unit Test Results (JWT Configuration Verification)
Class:
Test.PM.Unit.WebAppJWTConfigTest3. Integration Test Results (Combined Validation)
Class:
Test.PM.Integration.ConfigCorsAndJWTInWebAppTestThis test confirms the successful and simultaneous application of all CORS and JWT settings during a single module load, demonstrating complete feature integration.
cors-rest-appsmodule successfully./testcorscreated scuccessfullyhttps://www.example.com,https://pm.intersystems.com1Access-Control-Allow-Origin, ...(Confirmed comprehensive list)/testcorscreated scuccessfully60)1)900)cors-rest-appsmodule successfully..947516 sec.Test.PM.Integration.CorsAndJWTTest passed