Add login screen to jsreport and user management forms
Enabling the authentication
extension will add a login screen into jsreport studio and authenticate all incoming requests. The browser authentication is based on the cookie and API calls are verified using basic authentication or using bearer authentication verified against a configured authorization server.
Authentication
configuration adds a user administrator
into the system responsible for managing other users. This user can create users, remove users or change their passwords. All other individual users do not have permission to alter any other user.
To enable authentication add the following json into configuration.
"extensions": {
"authentication" : {
"cookieSession": {
"secret": "dasd321as56d1sd5s61vdv32",
"cookie": { <custom cookie options here> }
},
"admin": {
"username" : "admin",
"password": "password"
}
}
}
You can change admin username or password as you wish.
The list of custom cookie options to set is available here, for example, you can set { "cookie": { "secure": true } }
to indicate that the auth cookie will only be sent over HTTPS, which is a good security practice but it requires that your server works under https first.
"extensions": {
"authentication" : {
"cookieSession": {
"secret": "dasd321as56d1sd5s61vdv32",
"cookie": { "secure": true }
},
"admin": {
"username" : "admin",
"password": "password"
}
}
}
The jsreport custom users can be created from the entity tree plus button.
You need to add a Header to every request when this extension is enabled.
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
Where the hash is based on username and password:
base64(username:password)
You can use standard OData API to manage and query user entities. For example, you can query all users using:
This feature is in preview mode, it means that we have implemented all the necessary steps to complete the authentication flow with an authorization server but we are looking for real feedback about the feature to determine if something is missing or incomplete for other use cases. If you have such feedback don't hesitate to raise a question or open an issue.
If you would like to delegate authentication in the jsreport studio and in the jsreport http API to an authorization server that supports OpenID, you will need to use the authorizationServer
options. It is likely you will only need this if you would like to expose jsreport as a product with Single Sign-On support.
There are two main authentication cases supported when authorization server is enabled:
As requirements you will need to have this ready:
authorizationServer.studioClient
and authorizationServer.apiResource
configuration options. Additionally you may need to configure your auth server to allow redirect from a jsreport uri, assuming jsreport is hosted on localhost
the uri to allow is http://localhost:5488/auth-server/callback
, which is used during the Single Sign On when the login against your authorization server is successful and redirects back to jsreport.authorizationServer.usernameField
) linked to the user handled by your authorization server.authorizationServer.groupField
) linked to the user handled by your authorization server. this association has the extra advantage of not requiring to duplicate the user of your authorization server in jsreport, you can handle all the permissions in jsreport in groups and let your authorization server handle the user, you just need to associate them so after login the jsreport is able to identify which entities it has access to. When doing SSO to the jsreport studio you can customize the username shown there by setting another claim (authorizationServer.usernameField
) to the data linked to the user handled by your authorization server.You likely want this if you have a multi-tenant application, which handles authentication against a central authorization server and you want to delegate the access to the jsreport studio (reusing the same user credentials that your users already have) against the same authorization server.
In this case the authentication flow will be like this:
authorizationServer.endpoints.authorization
, authorizationServer.endpoints.jwks
, authorizationServer.endpoints.token
, authorizationServer.endpoints.userinfo
endpoints of your authorization server are going to be reached.authorizationServer.authorizationRequest.scope
).When you configure the studio to have this authentication flow you will probably want to integrate a button or link in your app that redirects the user to the studio.
<!-- Assumming jsreport is available on localhost:5488 -->
<a href="http://localhost:5488" />
if you do this then the user will be presented with the login page by default, requiring that user clicks the "LOGIN WITH XXXXX" to start the authentication with the authorization server. you can avoid the user needing to do that by instead using an extra parameter in the link from your app.
<!-- Assumming jsreport is available on localhost:5488 -->
<a href="http://localhost:5488/?authServerConnect" />
this will redirect the user to the authorization server directly, and provide a much better experience if the user is already logged-in with the authorization server.
You likely want this if you want to build an app that uses the jsreport http api, and want that the calls to the api are authenticated against tokens issued by an authorization server.
The authentication flow in this case looks like the following:
Authorization
header in any protected API call, the token must be sent using Bearer
auth schema, this means that all your requests to the jsreport API must be using a header: Authorization: Bearer <your token here>
authorizationServer.introspectionRequest.extraBody
) and credentials (authorizationServer.apiResource
) to the configured introspection endpoint (authorizationServer.endpoints.introspection
)active
field that describes if the token is valid or not ({ active: false | true }
), and optionally the response can contain a field (authorizationServer.usernameField
or authorizationServer.groupField
) which represents the linked jsreport user/group associated with this tokenauthorizationServer.endpoints.userinfo
is going to be called, the response from that call should contain a field (authorizationServer.usernameField
or authorizationServer.groupField
) with the linked jsreport username/group. the resolved username/group must be a valid and existing jsreport user/group, and if scope validation is configured authorizationServer.introspectionRequest.tokenValidScopes
we will also check that the token has a valid scopeAll of these steps are based on the OpenID standard, which is common to see in authorization servers that provide Single Sign On.
For a real implementation of jsreport + authorization server check our official sample.
To enable authentication, add the following json into configuration file.
"extensions": {
"authentication" : {
"cookieSession": {
"secret": "dasd321as56d1sd5s61vdv32"
},
"admin": {
"username" : "admin",
"password": "password"
},
// use the "authorizationServer" options when you plan to delegate authentication
// to an authorization server,
// this means that jsreport studio access and all protected jsreport http API calls will be validated with
// the configured authorization server, giving you the chance to expose
// jsreport as a product with Single Sign On support.
// see "Token based authentication using an authorization server" section of this document for more details and a link to a sample with real implementation.
"authorizationServer": {
// name for you authorization server (required), this is used for display purposes in
// the studio login (button "LOGIN WITH <name>").
"name": "AuthServer",
// issuer identifier (required), basically the identifier of your authorization server. it is usually a URL
"issuer": "http://localhost:9800",
// endpoints to the authorization server, you can easily find the information of these routes in the http://localhost:9800/.well-known/openid-configuration route of your authorization server
"endpoints": {
// (required) endpoint to get the public keys used to verify any JSON Web Token issued by the authorization server.
"jwks": "http://localhost:9800/.well-known/openid-configuration/jwks",
// (required) endpoint to start the authentication/consent with the authorization server
"authorization": "http://localhost:9800/connect/authorize",
// (required) endpoint to get a token
"token": "http://localhost:9800/connect/token",
// (required) endpoint to the Token introspection https://tools.ietf.org/html/rfc7662 of your authorization server.
"introspection": "http://localhost:9800/connect/introspect",
// (required) endpoint to the Userinfo https://openid.net/specs/openid-connect-core-1_0.html#UserInfo of your authorization server
"userinfo": "http://localhost:9800/connect/userinfo"
},
// (required) registered client in your authorization server, that identifies the jsreport studio
"studioClient": {
"clientId": "jsreport-studio",
"clientSecret": "---secret---",
// configure how the credentials (clientId and clientSecret) are going to
// be sent to the authorization server.
// valid values are "basic", "post", defaults to "basic"
"authType": "basic"
},
// (required) registered api resource in your authorization server, that identifies the jsreport http api
"apiResource": {
"clientId": "jsreport-api",
"clientSecret": "---secret---",
// configure how the credentials (clientId and clientSecret) are going to
// be sent to the authorization server.
// valid values are "basic", "post", defaults to "basic"
"authType": "basic"
},
// name of the field that jsreport will look at in the response from authorization server to
// use as the jsreport username associated with the token. (optional, defaults to "username")
"usernameField": "username",
// time in milliseconds that jsreport will wait before closing the request
// sent to the authorization server. (optional, defaults to 3500)
"timeout": 6000,
// additional configuration for the jsreport studio authentication (authorize request) against the authorization server
"authorizationRequest": {
// <string>| Array<string> the scopes that the jsreport studio authentication (authorize request)
// is going to request to the authorization server. default: ["openid", "profile"]
"scope": "openid profile" // or ["openid", "profile"]
},
// additional configuration for the token based authentication request against the authorization server
"introspectionRequest": {
// <string>| Array<string> list of valid scopes that the token needs to have in order to be considered valid, the token must have at least one scope that match with some item in the list in order to be considered valid
"tokenValidScopes": "jsreport", // or ["jsreport"]
// extra body to sent to the introspection request
"extraBody": {}
}
}
}
}