Open chillu opened 8 years ago
@chillu I'm happy to help out with this if you need some extra resource.
Re: the two auth flows - perhaps you could distinguish the authentication method from a request header. Either match the OAuth header or a custom SS session header.
@robbieaverill Thanks for your offer, we can absolutely use the help! :)
At the moment, the GraphiQL browser with the SilverStripe Content API will return empty results filtered by canView()
. A quick fix for this would be allowing basic auth passed in through HTTP headers - which is still a bit finnicky since you need to base64 encode them ready for the HTTP header (can't set user and password separately in GraphiQL). That's more of a missing feature in GraphiQL though, and basic auth is good enough for development work. Plus it already works out of the box in SilverStripe.
I don't think we need a viewer root node, but maybe I haven't understood the concept completely :)
Regarding an OAuth 2.0 server, this would implicitly add OAuth support to SS core, which is a fairly large security surface - and hence would need some form of RFC. Ideally we'd avoid running an XHR from the client for this, but rather auto-generate a token on the server, stored against the member. I'd rather not reuse the "remember me" token for this. It would have to be removed on logout, so a simple 1:1 relationship with sessions. And should have an expiry date which matches the PHP session. A separate module might also allow multiple API keys (and a UI to manage them), but that's out of scope for now.
The Oauth 2.0 server implementation should be a separate module, which can be applied through the SilverStripe\Control\RequestFilter
middleware - so the GraphQL module should only need some configuration to apply it to the /graphql
endpoint.
Apollo authorisation is easy through middleware.
Note that there's https://github.com/bigfork/silverstripe-oauth, which is an OAuth client, not server.
Does that give you enough to get started Robbie? This is really about "OAuth server in SS" more than in silverstripe/graphql.
As a simple start, you could just describe how to add basic auth to GraphiQL in the README?
Hey @chillu - sounds good, just a couple of things to clarify:
So the context for this is authenticating frontend calls to the GraphQL endpoints from within a SilverStripe site - i.e. a decoupled web app, rather than external applications accessing a SilverStripe GraphQL endpoint?
Ideally we'd avoid running an XHR from the client for this, but rather auto-generate a token on the server, stored against the member.
You're talking about a sort of pre/automatically authorized OAuth token set which the frontend can use to communicate with the backend? Seems sensible to me. It could also be augmented at a later date if required to provide full OAuth support for SilverStripe.
As a simple start, you could just describe how to add basic auth to GraphiQL in the README?
I agree - this would be worth doing to start with to establish the authentication integration process and ensure that it works. Then chuck something a bit meatier over the top.
I assume there's not a huge rush for this, but I'll work on this a little over the break and will aim to have it complete when we get back in.
Cheers!
So the context for this is authenticating frontend calls to the GraphQL endpoints from within a SilverStripe site - i.e. a decoupled web app, rather than external applications accessing a SilverStripe GraphQL endpoint?
Both. Dev will want to test their queries in external tools like GraphiQL.
You're talking about a sort of pre/automatically authorized OAuth token set which the frontend can use to communicate with the backend?
Yes, so for the SS4-internal authentication we'd only use one particular flow (auto generated token). I wouldn't start the OAuth implementation from scratch though, even for this relatively simple use case - I hope that the phpleague module would work for us, but needs more research since it'll add yet another core dependency (amount of code pulled in, amount of libraries)
I assume there's not a huge rush for this, but I'll work on this a little over the break and will aim to have it complete when we get back in.
Yep, we have a working solution at the moment (session-based), and you can use dev/graphiql
built into the silverstripe/graphql module for running queries.
AuthenticatorInterface
and a BasicAuthAuthenticator
which can be enabled via YAML configuration to authenticate via the native SS BasicAuth::requireLogin
method, and provide a Member
to GraphQL for use within query contexts.The interface is simple and easy enough to add custom authenticators to (dev only example).
I have made a start on implementing the PHP League OAuth2 server, however it requires PSR-7 compatible request and response interfaces, which SilverStripe doesn't have at the moment (related: silverstripe/silverstripe-framework#4484, mailing list discussion).
I spent a bit of time working on a HTTPResponse
adapter that implements the appropriate PSR-7 interfaces, but it is a big job and I'm not sure I'll have time to finish it in a reasonable timeframe outside of work commitments.
The actual implementation of the OAuth2 server shouldn't take too long since it comes with traits that provide most of the standard functionality - it's mostly just a case of connecting the interfaces repositories and entities to the appropriate SilverStripe DataObjects.
I'll keep the work I've done somewhere local and can chip away at it gradually, but perhaps we should roll-our-own OAuth based token authenticator in the meantime...?
cc @chillu / @sminnee
💯 ❤️ for a PSR-7 bridge
I've put together a simple PSR-7 adapter set, so the OAuth implementation seems to be coming along a bit better now.
@sminnee's API key module might be worth upgrading for SS4 and implementing in the meantime too.
sminnee/silverstripe-apikey#8 has a compatible authenticator added for GraphQL.
Merged: this adds a lightweight option for token based authentication in this GraphQL module until OAuth is available. cc @PapaBearNZ
Looks like other people already had a go at doing an integration with PHP League OAuth2 package https://github.com/advanced-learning/silverstripe-oauth2-server
I had a got at getting it running locally last night, but it's targeted to GraphQL 1, so it might need a bit of refactor to work with our latest version.
Session-based authentication relies on a manual mechanism for signing in (CMS login form). While we can already use programmatic authentication with Basic Auth over SSL, it's not very friendly to typical third party integrations. Implement an OAuth provider to make this more flexible, e.g. with http://oauth2.thephpleague.com/. It's unclear which flow we'd use (since we don't want any further user action beyond logging in to the session-based CMS).
Related: https://medium.com/the-graphqlhub/graphql-and-authentication-b73aed34bbeb#.ys9c7gc32 https://dev-blog.apollodata.com/a-guide-to-authentication-in-graphql-e002a4039d1 https://dev-blog.apollodata.com/auth-in-graphql-part-2-c6441bcc4302 http://graphql.org/graphql-js/authentication-and-express-middleware/