Skip to content
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

OAuth2/OpenID Connect implementation #270

Open
wants to merge 19 commits into
base: master
Choose a base branch
from

Conversation

dannywillems
Copy link
Member

@dannywillems dannywillems commented Oct 31, 2016

Don't loose time reviewing now. Lots of things must be done.
It was the first project I did in Ocsigen when I arrived so I suppose I need to change lots of things.

Sorry for the reviewer(s) but it's not something we can do in multiple PR. I will provide test applications.

Description.

This PR implements OAuth2.0 and OpenID Connect (server and client, independent) in ocsigen-start.

OAuth2.0 gives authorizations to external applications to get access to some informations.
For more information about OAuth2.0, see the official website or the RFC 6749. For information about OpenID Connect, see the official website or the RFC.

The implementation is focused on the Authorization code grant but other methods (Implicit grant, Password credentials and Client credentials grant) can be easily implemented independently by using the scopes and tokens module types. The only things which changed are the requests.

This implementation provides typed scopes and tokens, and give the possibility to implement its own scopes (module type SCOPE) tokens (module type IDTOKEN and TOKEN).

It's based on server-to-server communication: Os_[connect|oauth2]_client doesn't mean it's client-side code (compiled in JavaScript) but it's server-side code for the OAuth2.0 client (which is a server).

Organization.

For both (OAuth2.0 and OpenID Connect), there is the client and the server side, both are independent from ocsigen-start. By independent from ocsigen-start, it means we can have a service providing an OAuth2.0 server with ocsigen-start and the client is not necessary an ocsigen-start application (thanks @o-marshmallow who tested it).
The opposite (client using ocsigen-start and server not using ocsigen-start) must also be the case, but not tested. The problem with the opposite is lot of OAuth2.0 and OpenID Connect servers (GitHub, GitLab, Twitter, Facebook, etc) don't implement the RFC and this implementation is not entirely configurable (due to GET and POST parameters).

About modules types.

Each server and client defines a SCOPE and a TOKEN module type with CLIENT or SERVER module type depending on the purpose. It is necessary to redefine a new interface for each module because we don't have or need the same functions and same fields on tokens if it's an OAuth2.0 client or an OAuth2.0 server. For example, on the OAuth2.0 server, we need to transform the token in a JSON format (which is useless on the client) and on the OAuth2.0 client, we need to parse the JSON into a token (which is useless on the server). And all token server fields are not useful for the client and vice versa.

Even if some functions are in both side, I chose to not use include: I think it's clearer in this way.

OAuth2.0

The client (resp. server) implementation is provided in the files Os_oauth2_client.eliomi and Os_oauth2_client.eliom (resp. Os_oauth2_server.eliomi and Os_oauth2_server.eliom).

Shared pieces of code like services are in modules Os_oauth2_shared.eliomi and Os_oauth2_shared.eliom.

OpenID Connect

The client (resp. server) implementation is provided in the files Os_connect_client.eliomi and Os_connect_client.eliom (resp. Os_connect_server.eliomi and Os_connect_server.eliom).

As OpenID Connect is using OAuth2.0 protocol, the code for OpenID Connect is smaller and use functions and modules from OAuth2.0 implementation.

Todo

  • Work on timeout and number_of_timeout. timeout --> cycle_duration, number_of_timeout --> number_of_cycle.
  • Save token in eliom non volatile references. Tokens are saved in a list because as they will be expired after cycle_duration * number_of_cycle seconds, it doesn't matter if they are removed while restarting the server. They don't need to be saved in database (except the ID token for OpenID Connect.
  • Documentation: eliomdoc syntax.
    • Os_oauth2_client.eliomi
    • Os_oauth2_client.eliom
    • Os_oauth2_server.eliomi
    • Os_oauth2_server.eliom
    • Os_oauth2_shared.eliomi
    • Os_oauth2_shared.eliom
    • Os_connect_client.eliomi
    • Os_connect_client.eliom
    • Os_connect_server.eliomi
    • Os_connect_server.eliom
    • Os_db
  • Update done examples.
  • Manual in doc/manual-wiki. (not a tutorial).
  • Use HTTPS (see source code).
  • Redirection instead of change_page (see source code).
  • On the client, add a table with ID Token for external users. (for example, external_users). It must contain the server_id.
  • Tables must be in the schema ocsigen_start.
  • Expiration time in the JSON. Set to cycle_duration * number_of_cycle.
  • Use Os_types.
  • OCaml conventions (t_of_string, string_of_t).
  • Choose another name for counter_of_saved_token. Remove some information in the module types like counter_of_saved_token: it must be in the SERVER implementation.
  • Add examples in the template?
  • Add the tables in the SQL file of the template.
  • In the request information for code, use Os_current_user instead of using a set_userid function.
  • rpc_resource_owner_decline --> resource_owner_decline. Change also the types of the arguments.
  • Add basic services and handlers.

Fix #10

@Drup
Copy link
Member

Drup commented Oct 31, 2016

If you are going to implement oauth2/openid ... please make an external library. This will get more traction, more visibility and make a better library. Several people would be interested by such library.

@dannywillems
Copy link
Member Author

@Drup It depends a few on the users table and I created some tables in OS.
I thought about making an external library, but some pieces must remain in OS.

@Drup
Copy link
Member

Drup commented Oct 31, 2016

I thought about making an external library, but some pieces must remain in OS.

Of course, there are OS-specific parts that interact with the user tables, but do they have to do with oauth2 really, or just with authentication in general ?

@dannywillems
Copy link
Member Author

@Drup I can extract some part which is not OS-specific. Requests, Tokens representation, etc can be in an external library.

@dannywillems dannywillems force-pushed the oauth2_openid_connect branch 2 times, most recently from 68e414e to a342910 Compare November 3, 2016 16:15
@dannywillems
Copy link
Member Author

As suggested, I will (later, I don't know when) do an external service for OAuth2.0 and OpenID Connect.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Allow registration using OpenID
2 participants