keratin / authn-rb

Ruby client library for Keratin AuthN
https://github.com/keratin/authn
GNU Lesser General Public License v3.0
23 stars 3 forks source link

Working with multiple frontend domains #7

Closed nathanpalmer closed 7 years ago

nathanpalmer commented 7 years ago

The audience is setup as a static configuration within this library which makes it currently impossible to allow a single backend to service multiple front-end domains.

From the README.md example it shows this configuration

Keratin::AuthN.config.tap do |config|
  # The base URL of your Keratin AuthN service
  config.issuer = 'https://authn.myapp.com'

  # The domain of your application
  config.audience = 'myapp.com'

  # HTTP basic auth for using AuthN's private endpoints
  config.username = 'secret'
  config.password = 'secret'
end

and within id_token_verifier.rb it's grabbing the audience out of the configuration for verification.

def token_for_us?
  jwt[:aud] == Keratin::AuthN.config.audience
end

However, if we have multiple frontend servers hitting the same backend API we will only be able to service one of them.

I can set the configuration to one or the other but not both. It would be nice if we could pass a parameter (maybe optional) into subject_from as an audience override. That way we can take the referrer header from the request and pass it through. That should allow for the audience verification but allow it to work a bit more dynamically.

cainlevy commented 7 years ago

That sounds like a reasonable API for subject_from.

One difference between that solution vs a config.audiences array is that passing subject_from(token, audience: 'frontend1.domain.com') would prevent sessions from leaking from one subdomain to another. Is that desirable in your use case?

nathanpalmer commented 7 years ago

Right now, yes. Though I could see us wanting to share in the future, we don't have that now.

With that said I didn't see a way to allow sessions from multiple sites with the way things are setup today. Since the audience is based on the referrer when you login from the front-end it's always going to be the domain you are logging under.

nathanpalmer commented 7 years ago

I'm happy to throw out a PR on this. But before I do I just want to make sure that how I'm thinking about usage here aligns with yours. When you say this:

One difference between that solution vs a config.audiences array is that passing subject_from(token, audience: 'frontend1.domain.com') would prevent sessions from leaking from one subdomain to another.

It makes me think that the default behavior should allow for a session to be started on one domain (say frontend1.domain.com) and be recognized on the second domain (say frontend2.domain.com)

After reading through the code here, and on the main authn codebase, since we're taking the referer header that doesn't be the case. Should it be?

cainlevy commented 7 years ago

You've got me thinking about this as well. Both of the storage mechanisms (cookies, localStorage) in the JavaScript client are also single-origin. Well, cookies can be cross-origin, but only across subdomains and even then in an unfortunately permissive way.

So currently I'm thinking that signing in across multiple origins will involve one access token (aka identity token) for each, all backed by the same refresh token (aka AuthN session). An application that expects some user to switch from one origin to the next would check for an existing refresh token and request a new access token for the new origin. This, I think, would require the AuthN server to be configured with the full list of possible origins (or possibly a regex for dynamic subdomains).

The upshot for this issue at hand seems to be: let's double-down on one access token per origin and solve for cross-origin single sign-on later.

I'm happy to throw out a PR on this.

Thanks in advance! 👍

nathanpalmer commented 7 years ago

So currently I'm thinking that signing in across multiple origins will involve one access token (aka identity token) for each, all backed by the same refresh token (aka AuthN session).

Yeah, this sounds right to me.