Details

    • Type: New Feature
    • Status: In Progress
    • Priority: Major
    • Resolution: Unresolved
    • Affects Version/s: None
    • Fix Version/s: None
    • Component/s: None
    • Labels:
      None

      Description

      Here is dev list discussion for token based authentication work:
      http://markmail.org/message/vyskeh2wujqpkbwg

      1. JSON Web Tokens.pdf
        134 kB
        Deepak Dixit
      2. OFBIZ-9833-external-server.patch
        17 kB
        Jacques Le Roux
      3. OFBIZ-9833-external-server.patch
        17 kB
        Jacques Le Roux
      4. OFBIZ-9833-external-server.patch
        17 kB
        Jacques Le Roux
      5. OFBIZ-9833-external-server-test-example.patch
        2 kB
        Jacques Le Roux
      6. OFBIZ-9833-external-server-test-example.patch
        3 kB
        Jacques Le Roux
      7. rfc7519.pdf
        112 kB
        Deepak Dixit
      8. Token Based Authentication.pdf
        233 kB
        Deepak Dixit
      9. Token Based Authentication in Apache OfBiz.pdf
        131 kB
        Deepak Dixit

        Activity

        Hide
        deepak.dixit Deepak Dixit added a comment -

        Attaching document provided by Rahul Bhooteshwar on dev list

        Show
        deepak.dixit Deepak Dixit added a comment - Attaching document provided by Rahul Bhooteshwar on dev list
        Hide
        jacques.le.roux Jacques Le Roux added a comment -

        Thanks Deepak,

        I have done something for a custom project and will try to generalise it to include it in OFBiz. The goal is only to allow access to an external server running also an OFBiz instance. This can be useful for case when you want to access special features, like heavy report, etc.

        So it's simple but the bright side is also that's it's simple. It's included in OFBiz with very few changes and is totallly secure. Anyway I'll provide a patch for review.

        Show
        jacques.le.roux Jacques Le Roux added a comment - Thanks Deepak, I have done something for a custom project and will try to generalise it to include it in OFBiz. The goal is only to allow access to an external server running also an OFBiz instance. This can be useful for case when you want to access special features, like heavy report, etc. So it's simple but the bright side is also that's it's simple. It's included in OFBiz with very few changes and is totallly secure. Anyway I'll provide a patch for review.
        Hide
        jacopoc Jacopo Cappellato added a comment -

        Thank you Jacques.
        Deepak, I know you have also implemented a lightweight but complete solution to provide a web token authentication mechanism for clients performing API calls to OFBiz: it would be great if you could share it here for community review.

        Show
        jacopoc Jacopo Cappellato added a comment - Thank you Jacques. Deepak, I know you have also implemented a lightweight but complete solution to provide a web token authentication mechanism for clients performing API calls to OFBiz: it would be great if you could share it here for community review.
        Hide
        jacques.le.roux Jacques Le Roux added a comment -

        What I did is more like externalLoginKey but between 2 servers not 2 webapps on the same server. I just found today that I have still to iron some issues in order to generalise for OFBiz but not only.

        Show
        jacques.le.roux Jacques Le Roux added a comment - What I did is more like externalLoginKey but between 2 servers not 2 webapps on the same server. I just found today that I have still to iron some issues in order to generalise for OFBiz but not only.
        Hide
        jacques.le.roux Jacques Le Roux added a comment -

        I forgot to say that I picked JJWT to handle the token. Google API could be used but my experience with their way of "maintaining" their APIs (and products in general) is not "excellent"

        Show
        jacques.le.roux Jacques Le Roux added a comment - I forgot to say that I picked JJWT to handle the token. Google API could be used but my experience with their way of "maintaining" their APIs (and products in general) is not "excellent"
        Hide
        jacques.le.roux Jacques Le Roux added a comment -

        This is a quite interesting article even if it should be contextualised (no silver bullet): 10 Things You Should Know about Tokens

        Show
        jacques.le.roux Jacques Le Roux added a comment - This is a quite interesting article even if it should be contextualised (no silver bullet): 10 Things You Should Know about Tokens
        Hide
        deepak.dixit Deepak Dixit added a comment -

        Thanks Jacques for valuable inputs, I also used JJWT to handle token.

        Show
        deepak.dixit Deepak Dixit added a comment - Thanks Jacques for valuable inputs, I also used JJWT to handle token.
        Hide
        jacques.le.roux Jacques Le Roux added a comment -

        Here are 2 patches

        • OFBIZ-9833-external-server.patch is the real patch for the feature
        • OFBIZ-9833-external-server-test-example.patch is a patch to test the feature (do not commit)

        This works the same way than externalLoginKey but between 2 servers, not 2 webapps on the same server. The Single Sign On (SSO) is ensured by a JWT token, then all is handled as normal by a session on the reached server. The servers may or may not share a database but the loginUserIds on the 2 servers must be the same.

        Some notes:

        • We would need a Bearer token in Authorisation request header if we were using Oauth2. Here we don't, so no Bearer, KISS way.
        • OOTB the JWT masterSecretKey is not properly initialised and can not be OOTB. As we sign on on several servers, so have different sessions, we can't use the externalLoginKey way to create the JWT masterSecretKey. The best way to store the JWT masterSecretKey is to use a temporary properties file to load in a static final key when compiling and to drop the file just after compiling. This is simple and most secure. Of course the temporary properties file should be kept out of reach, outside the servers.
          It could be also loaded from a temporary network connection, etc. The magic words here are temporary but final!

        BTW here is an interesting site to check a JWT token https://www.jsonwebtoken.io/

        Please review and let me know your thoughts, thanks

        Show
        jacques.le.roux Jacques Le Roux added a comment - Here are 2 patches OFBIZ-9833 -external-server.patch is the real patch for the feature OFBIZ-9833 -external-server-test-example.patch is a patch to test the feature (do not commit) This works the same way than externalLoginKey but between 2 servers, not 2 webapps on the same server. The Single Sign On (SSO) is ensured by a JWT token, then all is handled as normal by a session on the reached server. The servers may or may not share a database but the loginUserIds on the 2 servers must be the same. Some notes: We would need a Bearer token in Authorisation request header if we were using Oauth2. Here we don't, so no Bearer, KISS way. OOTB the JWT masterSecretKey is not properly initialised and can not be OOTB. As we sign on on several servers, so have different sessions, we can't use the externalLoginKey way to create the JWT masterSecretKey. The best way to store the JWT masterSecretKey is to use a temporary properties file to load in a static final key when compiling and to drop the file just after compiling. This is simple and most secure. Of course the temporary properties file should be kept out of reach, outside the servers. It could be also loaded from a temporary network connection, etc. The magic words here are temporary but final ! BTW here is an interesting site to check a JWT token https://www.jsonwebtoken.io/ Please review and let me know your thoughts, thanks
        Hide
        jacques.le.roux Jacques Le Roux added a comment -

        Forgot to say that the purpose of this work is mostly to share the load on several servers...

        Show
        jacques.le.roux Jacques Le Roux added a comment - Forgot to say that the purpose of this work is mostly to share the load on several servers...
        Hide
        jacques.le.roux Jacques Le Roux added a comment -

        Forgot also to say (it's obvious in the patch) that I only tested on one server: localhost. But I don't see why it wouldn't work between two servers.

        Show
        jacques.le.roux Jacques Le Roux added a comment - Forgot also to say (it's obvious in the patch) that I only tested on one server: localhost. But I don't see why it wouldn't work between two servers.
        Hide
        jacques.le.roux Jacques Le Roux added a comment -

        Patch OFBIZ-9833-external-server.patch update: I just noticed the masterSecretKey var should be private

        Show
        jacques.le.roux Jacques Le Roux added a comment - Patch OFBIZ-9833 -external-server.patch update: I just noticed the masterSecretKey var should be private
        Hide
        jacques.le.roux Jacques Le Roux added a comment -

        This afternoon I discussed with Nicolas Malin about the proposed usage of properties for the JJWT masterSecretKey.

        As you may know I'm an old chap . So in my mind a static final field in Java would be linked when compiling, like for instance in C or C++. But Nicolas was septical on that. And then indeed it occured to me that I was speaking about a language which uses classes with Java bytecode and JIT compilation. So I had a look and found https://docs.oracle.com/javase/tutorial/essential/environment/properties.html where it's clear I was wrong.

        Anyway Nicolas suggested rather to use sed and uuidgen to dynamically modify the source file rather than using a properties file. And I think it's a great idea. I'll reflect that in the comment about it in ExternalLoginKeysManager.java and will create a new patch.

        Show
        jacques.le.roux Jacques Le Roux added a comment - This afternoon I discussed with Nicolas Malin about the proposed usage of properties for the JJWT masterSecretKey. As you may know I'm an old chap . So in my mind a static final field in Java would be linked when compiling, like for instance in C or C++. But Nicolas was septical on that. And then indeed it occured to me that I was speaking about a language which uses classes with Java bytecode and JIT compilation. So I had a look and found https://docs.oracle.com/javase/tutorial/essential/environment/properties.html where it's clear I was wrong. Anyway Nicolas suggested rather to use sed and uuidgen to dynamically modify the source file rather than using a properties file. And I think it's a great idea. I'll reflect that in the comment about it in ExternalLoginKeysManager.java and will create a new patch.
        Hide
        jacques.le.roux Jacques Le Roux added a comment -

        At r1813679, I have committed my proposition.

        I have not tested it between 2 servers yet, only locally where it works well. I'll do after this commit between my local instance and the trunk demo...

        Show
        jacques.le.roux Jacques Le Roux added a comment - At r1813679, I have committed my proposition. I have not tested it between 2 servers yet, only locally where it works well. I'll do after this commit between my local instance and the trunk demo...
        Hide
        jacques.le.roux Jacques Le Roux added a comment - - edited

        I have tested the Token Based Authentication between my local machine and the trunk demo. It works as expected. I have committed the rest of the work at revision: 1814363. It's complete now.

        Show
        jacques.le.roux Jacques Le Roux added a comment - - edited I have tested the Token Based Authentication between my local machine and the trunk demo. It works as expected. I have committed the rest of the work at revision: 1814363. It's complete now.
        Hide
        jacques.le.roux Jacques Le Roux added a comment -

        Something I want to note here, and will maybe create a Wiki page for, is about the security strategy suggested for storing the ExternalServerJwtMasterSecretKey in ExternalLoginKeysManager class.

        The question is simple: what is the best place to store a secret key? Of course there are several answers to this question and you might prefer your own, but be sure that it's as safe as you imagine.

        Here is a good summary about this question: https://security.stackexchange.com/questions/12332/where-to-store-a-key-for-encryption

        Traditionnaly in OFBiz we use properties files. There is at least 2 examples OOTB: janrain.apiKey and login.secret_key_string.
        So this seemed the most appropriate to me when I first thought about it. But then because here it's about getting access to another server I began to be more cautious. What happens if someone get a read access to the server and can read the content of this properties file? Then this person might get access to the other server, and the purpose of the JWT token is completly lost!

        The problem with a properties file is you need to keep it on the server to be able to read it when needed, I already commented about that above.

        You might be tempted to store the secret key in the Database. When it's only about a server it's IMO far from the best solution

        But when, like here, the functionnality allows access to another server then if the Database on the source server is compromised this possibly grants access to the other server for an attacker. Since the funcionnality allows access from one server to another, by transitivity this potentially allows access to more than 1 target server.

        For me the best simple solution is a file that you remove from the production server. Nicolas suggested, a file where the secret key is modified by sed using uuidgen on each build, and I agreed. But we missed something: the ExternalServerJwtMasterSecretKey must be the same on both servers (and etc.). So using uuidgen during build on each machine is innapropriate. Nevertheless the uuidgen solution is still interesting because it increase the difficulty for an attacker to know the ExternalServerJwtMasterSecretKey, but you could use a fixed ExternalServerJwtMasterSecretKey as well.

        A solution is to generate a uuid using uuidgen somewhere safe, or use a fixed ExternalServerJwtMasterSecretKey, and copy it using sed on the production servers. Since it's preferable to have the same deployment script on each production server I suggest to generate the uuid on a devlopment machine, or use a fixed ExternalServerJwtMasterSecretKey, and pass it to the deployment script. I recommend to not use an environment variable to pass the uuid as those can be considered weak:

        Several means can be used to pass the ExternalServerJwtMasterSecretKey to the deployment script, among them

        • copy it from the deployment machine using a temporary connection, possibly from an USB key removed after from the deployment machine to guarantee a total confidentiallity!
        • from an USB key removed after from the production servers to guarantee a total confidentiallity (harder with cloud solutions)
        • manually by the OPS somehow (again avoid an environment variable)
        • etc.
        Show
        jacques.le.roux Jacques Le Roux added a comment - Something I want to note here, and will maybe create a Wiki page for, is about the security strategy suggested for storing the ExternalServerJwtMasterSecretKey in ExternalLoginKeysManager class. The question is simple: what is the best place to store a secret key? Of course there are several answers to this question and you might prefer your own, but be sure that it's as safe as you imagine. Here is a good summary about this question: https://security.stackexchange.com/questions/12332/where-to-store-a-key-for-encryption Traditionnaly in OFBiz we use properties files. There is at least 2 examples OOTB: janrain.apiKey and login.secret_key_string. So this seemed the most appropriate to me when I first thought about it. But then because here it's about getting access to another server I began to be more cautious. What happens if someone get a read access to the server and can read the content of this properties file? Then this person might get access to the other server, and the purpose of the JWT token is completly lost! The problem with a properties file is you need to keep it on the server to be able to read it when needed, I already commented about that above. You might be tempted to store the secret key in the Database. When it's only about a server it's IMO far from the best solution see point 7 in link above https://stackoverflow.com/questions/13991100/where-do-you-store-your-secret-key-in-a-java-web-application . But when, like here, the functionnality allows access to another server then if the Database on the source server is compromised this possibly grants access to the other server for an attacker. Since the funcionnality allows access from one server to another, by transitivity this potentially allows access to more than 1 target server. For me the best simple solution is a file that you remove from the production server. Nicolas suggested, a file where the secret key is modified by sed using uuidgen on each build, and I agreed. But we missed something: the ExternalServerJwtMasterSecretKey must be the same on both servers (and etc.). So using uuidgen during build on each machine is innapropriate. Nevertheless the uuidgen solution is still interesting because it increase the difficulty for an attacker to know the ExternalServerJwtMasterSecretKey, but you could use a fixed ExternalServerJwtMasterSecretKey as well. A solution is to generate a uuid using uuidgen somewhere safe, or use a fixed ExternalServerJwtMasterSecretKey, and copy it using sed on the production servers. Since it's preferable to have the same deployment script on each production server I suggest to generate the uuid on a devlopment machine, or use a fixed ExternalServerJwtMasterSecretKey, and pass it to the deployment script. I recommend to not use an environment variable to pass the uuid 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 Several means can be used to pass the ExternalServerJwtMasterSecretKey to the deployment script, among them copy it from the deployment machine using a temporary connection, possibly from an USB key removed after from the deployment machine to guarantee a total confidentiallity! from an USB key removed after from the production servers to guarantee a total confidentiallity (harder with cloud solutions) manually by the OPS somehow (again avoid an environment variable) etc.
        Hide
        jacques.le.roux Jacques Le Roux added a comment -

        BTW, as it can help, here is the sed syntax I used to change the ExternalServerJwtMasterSecretKey .
        With uuidgen

        sed -i /ExternalServerJwtMasterSecretKey/s//$(uuidgen)/\2 framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/ExternalLoginKeysManager.java
        

        Without uuidgen

        sed -i /ExternalServerJwtMasterSecretKey/s//yourKeyValue/\2 framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/ExternalLoginKeysManager.java
        
        Show
        jacques.le.roux Jacques Le Roux added a comment - BTW, as it can help, here is the sed syntax I used to change the ExternalServerJwtMasterSecretKey . With uuidgen sed -i /ExternalServerJwtMasterSecretKey/s //$(uuidgen)/\2 framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/ExternalLoginKeysManager.java Without uuidgen sed -i /ExternalServerJwtMasterSecretKey/s //yourKeyValue/\2 framework/webapp/src/main/java/org/apache/ofbiz/webapp/control/ExternalLoginKeysManager.java

          People

          • Assignee:
            deepak.dixit Deepak Dixit
            Reporter:
            deepak.dixit Deepak Dixit
          • Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

            • Created:
              Updated:

              Development