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

Decompositioning, implement Fosite #62

Merged
merged 114 commits into from
May 29, 2016
Merged

Decompositioning, implement Fosite #62

merged 114 commits into from
May 29, 2016

Conversation

aeneasr
Copy link
Member

@aeneasr aeneasr commented Mar 22, 2016

This PR is a refactor and a partial re-code of Hydra. It will mark version 0.1-beta and will include

Tagline: "A micro-service OAuth2, OpenID Connect and policy decision point provider written in Go". Check also this milestone: https://github.com/ory-am/hydra/milestones/0.1-beta

@aeneasr aeneasr added the feat New feature or request. label Mar 22, 2016
@aeneasr aeneasr self-assigned this Mar 22, 2016
@aeneasr aeneasr added this to the 0.1-beta milestone Mar 22, 2016
@aeneasr
Copy link
Member Author

aeneasr commented Mar 22, 2016

@leetal keep an eye out for this one :)

@aeneasr aeneasr mentioned this pull request Mar 22, 2016
@leetal
Copy link
Contributor

leetal commented Mar 22, 2016

@arekkas i sure will! :)
Den 22 mars 2016 16:15 skrev "Aeneas" notifications@github.com:

@leetal https://github.com/leetal keep an eye out for this one :)


You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub
#62 (comment)

@aeneasr
Copy link
Member Author

aeneasr commented Mar 22, 2016

Repositories relevant for the refactor:

@aeneasr
Copy link
Member Author

aeneasr commented Mar 23, 2016

The following chart is a very basic architecture overview.

imag0480

CLI

The CLI hydra will replace the functionality that currently resides in hydra-host and talk through HTTP REST with hydra-host. The admin needs to log in using app credentials. If no app is registered in Hydra, a OTP (one time password) will be printed to stdout by hydra-host. The admin needs to use that OTP in order to create the first administrative client.

idp.hydra.abc.com

I decided to move the identity provider part away from Hydra's core. Instead, it will reside in a microservice. Anyone who wishes to use LDAP or an existing user database as an identity source can do that by implementing the required HTTP REST interfaces (not defined yet).

Identity provider(s) will be added using the CLI: hydra idp add http://...

connector.hydra.abc.com

The connector is responsible for delegating a user to Google, Microsoft and other third party authentication services and returning "user info" to hydra. Hydra will then use that user info to find a match at the identity provider and confirm that the user exists. The matching will be done internally in hydra (currently known as "oauth2 connection")

Connectors will be added using the CLI: hydra connector add http://....

Resource Provider Endpoint

The middleware and client library will be rewritten and offer two interface:

  1. Check if a token is valid (checks token expiry, token revokation, scope)
  2. Do what 1 does plus access control through policies

@aeneasr
Copy link
Member Author

aeneasr commented Mar 23, 2016

The reworkings of connectors and identity providers let us additionally paralelize lookups with high efficiency. Cash. :)


}

func (o *OAuth2Handler) TokenHandler(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

god, this looks so much cleaner already..

@aeneasr
Copy link
Member Author

aeneasr commented Mar 23, 2016

Separating idp.hyra.abc.com, singin.hydra.abc.com and connector.hydra.abc.com is maybe not a good idea. The question is, if idp.hydra.abc.com is even required and if singin and connector should be one. It might be good if hydra took over a lot of the complexity and on the same time, it complicates service flows.

@aeneasr
Copy link
Member Author

aeneasr commented Mar 23, 2016

Complicated: The login endpoint could redirect back to hydra which would redirect that request to Google, MS, and so on. The callback would be a hydra endpoint which would validate the authentication request through a "connection" database lookup and a quick check in at the idp and redirect to the consent endpoint which would issue the consent token.

@aeneasr
Copy link
Member Author

aeneasr commented Mar 23, 2016

Alternative: The login endpoint handles all the third party authentication on its own and is simply responsible for returning a consent token. This would require much more sophisticated login / consent endpoints

@aeneasr
Copy link
Member Author

aeneasr commented Mar 29, 2016

One question that has me spinning in circles is how to handle social / remote logins. There are two possibilities I see right now.

Terminology:

  • IdP(s): Identity Provider(s)
  • Remote / Social IdP: This could be Google, Microsoft, ...
  • Local IdP: In monolithic applications, there is always a "user database" where the username, email and password are stored and retrieved. A local IdP is a such a user database which is usually under full control of the hydra administrator and is run in the same network or domain.

The remote party is seen as a standalone IdP

The remote idps (e.g. google) are considered a local idp: When the users signs in using a social login, no lookup is made if that user exists at the local idp. This basically means that we can skip the sign up process.

Workflow (simplified)

  1. User chooses to use google for authentication
  2. User is redirected to https://hydra.com/oauth2/auth?idp=google&client_id=...
  3. User is redirected to https://google.com/sign-in
  4. After successful authorization at google, the user is redirected to e.g. https://hydra.com/idp/google/callback
  5. Hydra authenticates the user / validates the request by e.g. decoding the id token or making some sort of request to google
  6. Hydra asks for the users consent
  7. Hydra issues an authorization code / access token

Pro:

  • Reduced complexity: No roundtrip or registration at the "local" identity provider required when using social logins
  • No need to introduce a functionality like "social connectors" because we can use social idps in the same fashion we use local idps.

Cons:

  • Not sure how this scenario would work out if local and social IdPs are used. Because local IdP would create a user account but social IdP would not.
  • Not sure how to fetch user data in an orderly fashion from social IdPs. We would need some sort of adapter, but user profile requirements vary a lot across projects.
  • Any user can simply "sign up/in" using a social IdP (if activated). There is no "control" possible. Not sure how banning accounts, invitation only sign up and similar things would work.
  • If the remote party discontinues services or bans the user account, the local user account will be lost as well.

The remote party acts as an intermediate connector

In contrary to above, the remote party is an identity provider as well, but hydra acts as a bridge between it and the local idp. Every user requires thus an account at the local idp and the remote idp in order to sign in.

Workflow (simplified)

  1. User chooses to use google for authentication
  2. User is redirected to https://hydra.com/oauth2/auth?connector=google&client_id=...
  3. User is redirected to https://google.com/sign-in
  4. After successful authorization at google, the user is redirected to e.g. https://hydra.com/connectors/google/callback
  5. Hydra authenticates the user / validates the request by e.g. decoding the id token or making some sort of request to google
  6. Hydra checks the connection database. It contains fields remote_id, local_id and connector. If the user id returned by the connector exists, hydra uses the local id for further lookup.
  7. Hydra checks the local IdP(s) for the found local user id and may ask if that user can be authenticated (this could also be done through policies)
  8. If all of the above was successful, hydra will ask for the user's consent
  9. Hydra issues an authorization code / access token

Pro / Con: TBD

@@ -20,9 +20,11 @@ type Context struct {
}

type Client interface {
TokenFromRequest(r http.Request) string

ActionAllowed(token string, action *Action) (*Context, error)

Authorized(token string, scopes ...string) (*Context, error)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There will be no more middleware, just one client. This will clean up the code base a lot. This interface should basically be implemented by any client in any language. Maybe we can use something like Thrift to build a client library for various languages

@aeneasr
Copy link
Member Author

aeneasr commented Mar 30, 2016

Connection needs an endpoint which returns

{
   Authorization: 'bearer .....',
}

or some other value for non-OAuth2 requests. This allows for sign up trickery

@aeneasr
Copy link
Member Author

aeneasr commented Apr 13, 2016

Alternative: The login endpoint handles all the third party authentication on its own and is simply responsible for returning a consent token. This would require much more sophisticated login / consent endpoints

is actually the smarter choice, if the endpoint is returning a "connection token" including the remote_id

@aeneasr
Copy link
Member Author

aeneasr commented Apr 22, 2016

The consent token should be able to carry a remote subject and id

@aeneasr
Copy link
Member Author

aeneasr commented Apr 22, 2016

@aeneasr
Copy link
Member Author

aeneasr commented Apr 22, 2016

I have decided to switch from postgres to RethinkDB and use the changes() feature to minimize db queries and significantly increase performance.

@aeneasr
Copy link
Member Author

aeneasr commented May 1, 2016

@aeneasr
Copy link
Member Author

aeneasr commented May 8, 2016

@iOliverNguyen
Copy link

iOliverNguyen commented May 11, 2016

Could you list all Hydra APIs (implemented or will be implemented when #62 is merged) in Apiary? This would help us decide whether Hydra is fitted to our system. Thank you a lot :)

@aeneasr
Copy link
Member Author

aeneasr commented May 11, 2016

Already on it :)

@aeneasr
Copy link
Member Author

aeneasr commented May 29, 2016

0.1-beta is ready. Please try things, and break them. :D

@tacurran
Copy link
Member

@aeneasr good history and well written too

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

Successfully merging this pull request may close these issues.

5 participants