////
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.
////

= Passwords and JWT (JSON Web Tokens) usage
== How are set and used passwords and JWT  in Apache OFBiz
The Apache OFBiz Project
Release trunk

:imagesdir: ../../themes/common-theme/webapp/images/img/
ifdef::backend-pdf[]
:title-logo-image: image::OFBiz-Logo.svg[Apache OFBiz Logo, pdfwidth=4.25in, align=center]
:source-highlighter: rouge
endif::[]

=== Passwords

Demo and seed passwords are stored in files loaded through security ofbiz-component.xml. To know more about that be sure to read:


* https://cwiki.apache.org/confluence/display/OFBIZ/Apache+OFBiz+Technical+Production+Setup+Guide[The technical production setup guide] notably "Initial Data Loading" and "Security Settings" sections
* https://cwiki.apache.org/confluence/display/OFBIZ/How+to+secure+your+deployment[How to secure your deployment]

[CAUTION]
These configuration steps are not to be neglected for the security of a *production environment*

=== JWT usage

https://en.wikipedia.org/wiki/JSON_Web_Token[As says Wikipedia]:
____
JSON Web Token (JWT) is an Internet standard for creating JSON-based access tokens that assert some number of claims.
____


We currently use JWT in 2 places:

. To let users safely recreate passwords (in backend and frontend)
. To allow SSO (Single Sign-on) jumpings from an OFBiz instance to another on another domain, by also using https://en.wikipedia.org/wiki/Cross-origin_resource_sharing[CORS] (
Cross-origin resource sharing) on the target server


==== How to secure JWT
When you use JWT, in order to sign your tokens, you have the choice of using a sole so called secret key or a pair of public/private keys: https://jwt.io/introduction/.

You might prefer to use pair of public/private keys, for now by default OFBiz uses a simple secret key. Remains the way how to store this secret key. https://security.stackexchange.com/questions/87130/json-web-tokens-how-to-securely-store-the-key[This is an interesting introduction about this question].

. The first idea which comes to mind is to use a property in the security.properties file. It's safe as long as your file system is not compromised.
. You may also pick a SystemProperty entity (overrides the file property). It's safe as long as your DB is not compromised.
. We recommend to not use an environment variable as those can be considered weak:
* http://movingfast.io/articles/environment-variables-considered-harmful
* https://security.stackexchange.com/questions/49725/is-it-really-secure-to-store-api-keys-in-environment-variables

. You may want to tie the encryption key to the logged in user. This is used by the password recreation feature. The JWT secret key is salted with a combination of the current logged in user and her/his password. This is a simple and effective safe way.
. Use a https://tools.ietf.org/html/rfc7519#section-4.1.7[JTI] (JWT ID). A JTI prevents a JWT from being replayed. This https://auth0.com/blog/blacklist-json-web-token-api-keys/[auth0 blog article get deeper in that].  The same is kinda achieved with the password recreation feature. When the user log in after the new password creation, the password has already been  changed. So the link (in the sent email) containing the JWT for the creation of the new password can't be reused.
. Tie the encryption key to the hardware. You can refer to this https://en.wikipedia.org/wiki/Hardware_security_module[Wikipedia page] for more information.
. If you want to get deeper in this get to this https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Key_Management_Cheat_Sheet.md#user-content-storage[OWASP documentation]

Note: if you want to use a pair of public/private keys you might want to consider  leveraging the Java Key Store that is also used by the "catalina" component to store certificates. Then don't miss to read:

* https://cryptosense.com/blog/mighty-aphrodite-dark-secrets-of-the-java-keystore/
* https://neilmadden.blog/2017/11/17/java-keystores-the-gory-details/

Also remember that like everything a https://www.sjoerdlangkemper.nl/2016/09/28/attacking-jwt-authentication/[JWT can be attacked] and, though not used or tried in OFBiz yet,  https://github.com/auth0/java-jwt#using-a-keyprovider[a good way is to mitigate an attack by using a KeyProvider]. I have created https://issues.apache.org/jira/browse/OFBIZ-11187[OFBIZ-11187] for that.

===== Properties

The _security.properties_ file contains five related properties:

    # -- If false, then no externalLoginKey parameters will be added to cross-webapp urls
    security.login.externalLoginKey.enabled=true

    # -- Security key used to encrypt and decrypt the autogenerated password in forgot password functionality.
    #    Read Passwords and JWT (JSON Web Tokens) usage documentation to choose the way you want to store this key
    login.secret_key_string=p2s5u8x/A?D(G+KbPeShVmYq3t6w9z$B&E)H@McQfTjWnZr4u7x!A%D*F-JaNdRg

    # -- Time To Live of the token send to the external server in seconds
    security.jwt.token.expireTime=1800

    # -- Enables the internal Single Sign On feature which allows a token based login between OFBiz instances
    # -- To make this work you also have to configure a secret key with security.token.key
    security.internal.sso.enabled=false

    # -- The secret key for the JWT token signature. Read Passwords and JWT (JSON Web Tokens) usage documentation to choose the way you want to store this key
    security.token.key=D*G-JaNdRgUkXp2s5v8y/B?E(H+MbPeShVmYq3t6w9z$C&F)J@NcRfTjWnZr4u7


There are also SSO related SystemProperties in __SSOJWTDemoData.xml__:
[source,xml]
----
    <SystemProperty systemResourceId="security" systemPropertyId="security.internal.sso.enabled" systemPropertyValue="false"/>
    <SystemProperty systemResourceId="security" systemPropertyId="SameSiteCookieAttribute" systemPropertyValue="strict"/>
----

==== Internal SSO
The introduction of the same-site attribute set to 'strict' for all cookies prevents the internal Single Sign On feature. Why is clearly explained https://web.dev/samesite-cookies-explained[here].

So same-site attribute set to 'none' is necessary for the internal SSO to work, https://github.com/whatwg/fetch/issues/769['lax' is not enough]. So if someone wants to use the internal SSO feature s/he also needs to use  the CSRF token defense. If s/he wants to be safe from CSRF attacks. Unfortunately, due backporting difficulties, this option is currently (2020-04-15) only available in trunk.

===== Fecth API
An alternative would be to use the Fetch Javascript API with the

[source]
----
credentials: "include"
----
option https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API#Differences_from_jQuery[to enable CORS]. https://javascript.info/fetch-crossorigin#credentials[Here is an example]

For those interested, there are more information in https://issues.apache.org/jira/browse/OFBIZ-11594



=== Last but not least
Be sure to read https://cwiki.apache.org/confluence/display/OFBIZ/Keeping+OFBiz+secure[Keeping OFBiz secure]
