WebID-TLS authentication does not support hand-off. Servers should always be in OIDC mode, which supports hand-off.
In OIDC mode, logging in can happen in two ways:
Importantly, both ways result in an OIDC login.
Related: https://github.com/solid/solid-auth-client/issues/44, https://github.com/solid/solid/issues/138#issuecomment-387439471
I'll respond to this issue with caution as religious wars on this topic have slowed down development.
What I'll say is that
I've removed the tags on this, as I think it needs more discussion.
Is there a definition of 'hand-off'?
From an architecture point of view, WebID-TLS needs to check that the public key in the WebID matches that in the X.509 client certificate. Any server is capable of performing this check, without out of band information. At this point, a shared secret can be established e.g. (cookie or token) in order to make future requests faster.
So, the minimum requirement for WebID-TLS identity provider is to host the WebID as turtle. Which currently is the case.
semver.major is correct. _If_ we apply this change, then it will require a major version increase.
I'll get back to your other points later today.
@melvincarvalho I dunno if it's a religious issue, more an engineering and strategic one.
The way I see it, it's a matter of inclusion, and future-proofing.
Inclusion: TLS certificate users can participate in the OIDC-mode pod ecosystem. But the reverse isn't true - username & passwd users (or any other authn system) can't interact with TLS-mode pods.
Future-proofing: Similarly, OIDC (being an auth delegation protocol) ensures that any other authentication method (such as WebAuthentication, which is now rolled out in most major browsers) can be dropped in smoothly, without any changes to authentication clients or app code. Which is again, not the case with TLS-mode pods.
So, I suppose the question is - what are your concerns? You'll still be able to use TLS certs daily, with oidc-mode pods.
I guess @dmitrizagidulin just said it all. It's not religion, it's compatibility.
OIDC is universal, as it includes TLS, username/password, and any authentication we might want in the future (fingerprint, QR code, CAS, …).
TLS only includes TLS.
Have you seen all the 401 issues on Gitter and everywhere else the last couple of months? Literally every single one of them was because people tried to use TLS as a hand-off protocol. It never worked and never will. The intention has _always_ been to remove TLS mode with the introduction of OIDC (which is not the same as removing support for logging in with a client certificate). So let's just leave this legacy method behind, and do this at the first major version change, which will be 5.
Actually, @melvincarvalho:
node-solid-server in TLS mode is something I use on a daily basis
Was the same for me until yesterday. Switched to OIDC mode and things are still working.
I'd propose you try to switch and report what breaks.
Are there any apps in particular that would not work for you?
If so, we should focus on porting these apps to solid-auth-client.
@dmitrizagidulin @RubenVerborgh Thanks for responding.
The intention has always been to remove TLS mode with the introduction of OIDC
This is not the case at all.
OIDC was added as a point of flexibility for authentication. The idea was to be able to use either TLS in its current or a bearer token with OIDC.
So the principle behind undertaking this work was that "AND" is better than "OR".
ie instead of :
auth=tls
auth=oidc
we have
auth-oidc,tls
There's a few barriers for why this isnt quite the case today, and we can fix them.
The TLS auth is on every resource. It's simple, easy, has well supported tooling, can be used with curl, has a low attack surface etc. A more complex workflow requires upgrading of everyone that uses TLS. For example, I've been trying to establish how to use a TLS certificate to update an OIDC server (from the command line), for several months. The answer is that no one knows, it's incredibly complex, and will require a lot of reengineering.
The disadvantage of having TLS on every resource (as opposed to just one), is that some user agents do not have an optimal user experience (either for GET or PUT, or even ajax mashups). So as a work around some users may with to turn off the TLS approach on every resource.
So in summary the aim of this was to increase options. The aim should surely be to get OIDC mode working as well as TLS mode, then allow TLS mode to work as well as OIDC mode. Then the problem goes away.
Edit: I added "from the command line" above
@melvincarvalho So I think the original title of this issue may be confusing -- the idea is to get rid of the TLS-only mode, which doesn't allow for interacting with any other modes.
You'll still be able to use TLS certs to authenticate in the oidc mode pods.
@RubenVerborgh here's an example of an issue open since october to do what can be done in one line on a WebID-TLS server
https://github.com/solid/solid/issues/133
Here is a partial outline of the steps required in OIDC that I've gathered :
Steps
gets the client_id / client_secret
uses those two to get back the bearer token
Static registration
google, facebook, twitter and others, have a web form that you can fill out to register an application and it gives you a token (which you then paste into that application's config, or pass it as a cli param, etc) so that's static registration our Solid auth clients use dynamic registration (we don't have the 'register an app' form implemented)
Dynamic registration
for a cli app (or any sort of server-side app) to get a solid server auth token, it has to do the following -- 1) perform dynamic registration (if it hasn't already -- if it has, it loads that registration from storage). 2) generate an authorization URL, for a user to open. 3) at the same time, the app has to listen on a localhost port, for the return callback. 4) The user opens the authz link, logs in, and is redirected by the server to the callback url (which the app is listening on) the app parses the callback url, extracts the token from it since you have a TLS cert already, you should be able to skip several of those steps but that functionality needs to be implemented.
Howto
how to register at the /register endpoint, which params to provide, and document it
Example:
https://github.com/solid/webid-oidc-spec/blob/master/example-workflow.md#23-dynamic-client-registration-first-time-only
If this is the first time a Provider and a Relying Party are encountering each other, the RP must perform Dynamic Client Registration. Note: This is an operation that happens under the hood, and does not involve the user. All compliant OIDC clients have this functionality built in.
The intention has always been to remove TLS mode with the introduction of OIDC
This is not the case at all.
Yes it is, @timbl confirmed this to me this in an auth discussion last week.
So the principle behind undertaking this work was that "AND" is better than "OR".
Exactly. OIDC mode supports both username/password AND client certificate.
So in summary the aim of this was to increase options.
And we have. But we need everyone to play along, and playing along means having your server in OIDC mode, so you support everything.
solid/solid#133
So we should make a command-line tool.
@RubenVerborgh
Yes it is, @timbl confirmed this to me this in an auth discussion last week.
I'd like to understand the complete proposal, do you have minutes, or can summarize the context?
Also : https://gitter.im/solid/node-solid-server?at=5af4f44d52194a4a67d73522
I feel we need a good statement of the strategic change @RubenVerborgh is suggesting, and side-by-side the status quo is. And the posibility elaborate the arguments around and between each.
How about the wiki?
I'd like to understand the complete proposal, do you have minutes, or can summarize the context?
So imagine the configuration conceptually as follows:
{
auth: {
askClientCertOnEveryRequest: bool,
oidc: {
enabled: bool,
usernamePassword: bool,
clientCert: bool,
}
}
}
auth: "tls"Given the above, the meaning of auth: "tls" is:
{
auth: {
askClientCertOnEveryRequest: true,
oidc: {
enabled: false
}
}
}
auth: "oidc"Given the above, the meaning of auth: "oidc" is:
{
auth: {
askClientCertOnEveryRequest: false,
oidc: {
enabled: true,
usernamePassword: true,
clientCert: true,
}
}
}
The auth: "tls" option must go because there is no OIDC in there. Also, the whole auth option is confusing because it implies a choice, whereas if you set it to "oidc", you actually also get WebID-TLS.
We could reshape the config such that it becomes:
{
auth: {
askClientCertOnEveryRequest: bool,
oidc: {
enabled: true,
usernamePassword: bool,
clientCert: bool,
}
}
}
So you can enable and disable things as you wish.
However, this is _not_ what is currently implemented. This proposal is about removing the TLS-only mode as _currently_ implemented, not about removing or excluding any possible future interpretation of auth: "tls" (which is confusing and should go anyways, because the auth option is multi-valued in practice, not single-valued).
@RubenVerborgh thanks for clarifying the proposal.
So a number or things :
Firstly, the auth config option is confusing. We should try and document the current behaviour e.g. in : https://github.com/solid/node-solid-server/blob/master/bin/lib/options.js#L68
Originally there was no auth flag in the config. I think it was added to distinguish between the TLS branch and the OIDC branch. The aim, was to add both OIDC functionality and TLS together.
What happened in practice was that in the OIDC branch, TLS was turned OFF for all resources except one. And bearer tokens were added for all resources.
What I think some had assumed was that bearer tokens would be eventually turned on for all resources. But I suppose that's not how it's been implemented so far -- of course OIDC is still a work in progress.
Regarding your proposal for config, is this a kind of pseudo code, or do you actually want to change the config? For example nested options might not play that well on the command line.
So, how about the idea of turning on bearer tokens for all resources in TLS mode? Good idea? Bad Idea?
WebID-TLS authentication does not support hand-off.
I think we established on gitter that you can achieve hand-off by adding a key pair to your user agent / WebID. In firefox this is a one click operation ie as many clicks a cert or logic pop up.
Hi Melvin,
Firstly, the auth config option is confusing.
Yeah, hence this PR :wink:
We should try and document the current behaviour
I think we should just get rid of it and fix it instead. It was never meant to function this way.
I think it was added to distinguish between the TLS branch and the OIDC branch.
Indeed.
The aim, was to add both OIDC functionality and TLS together.
Yes, and OIDC mode does that now.
But we can also add a switch to alwaysRequestClientCert, which is what I think you want.
What happened in practice was that in the OIDC branch, TLS was turned OFF for all resources except one. And bearer tokens were added for all resources.
Indeed, that was by design.
As I said, let's add alwaysRequestClientCert.
OIDC is still a work in progress.
Not really, it works well. Bug reports with reproducible steps welcome.
Regarding your proposal for config, is this a kind of pseudo code, or do you actually want to change the config?
I actually want to change the config. Names can be more brief, but that's the idea.
For example nested options might not play that well on the command line.
We already have them. A simple matter of using a dot to traverse the hierarchy.
So, how about the idea of turning on bearer tokens for all resources in TLS mode?
No, my proposal removes the whole concept of modes. You should be able to turn on and off TLS and OIDC independently.
I think we established on gitter that you can achieve hand-off by adding a key pair to your user agent / WebID.
That wasn't hand-off, but switching accounts.
How would someone set alwaysRequestClientCert switch, for the server to support both:
To clarify, such server would only act as rww data origin (eg. open source project issues tracker), it would not have any identity provider responsibilities.
How one would someone set alwaysRequestClientCert switch, for the server to support both:
- clients which only use WebID-TLS (eg. bots, smart proxies)
- clients which only use WebID-OIDC (eg. in browser apps)
Careful, the question is (unintentionally) misleading, in two ways:
What alwaysRequestClientCert adds is that WebID-TLS authentication can be applied to _any_ resource, instead of having one special resource that handles auth (as is the case with the current OIDC mode).
To clarify, such server would only act as rww data origin (eg. open source project issues tracker), it would not have any identity provider responsibilities.
That is orthogonal: the server can still act as an OIDC provider, and additionally ask for a client certificate on every resource. Not saying it would be useful, just that it is possible.
That is orthogonal: the server can still act as an OIDC provider, and additionally ask for a client certificate on every resource. Not saying it would be useful, just that it is possible.
I see OIDC provider as very specific responsibility which not all solid servers, which support WebID-OIDC authenticated requests have to support as well. Taking example of one of such deployments, let's say hypothetical issue tracker for RDF.js, how configuration would work for it to
By authenticated requests, I mean that a client can make requests (read/write) to ACL protected resources on any number of origins other than user's OIDC provider. Maybe I misunderstand how solid implements it but I assume TLS client certs for WebID-TLS and Bearer tokens for WebID-OIDC.
- OIDC provides both username/password and WebID-TLS login (and can provide more in the future)
Does solid server support all those authentication mechanisms as part if its identity provider role, or it would also provide them for cases like one above (server accepts authenticated requests but does NOT act as OIDC provider)?
@RubenVerborgh @elf-pavlik
WebID-OIDC, while very promising, should be considered a work in progress because :
This last part is feedback from several one on one sessions where new developers have tried to create hello world apps, and have given up as the bar is too high.
Thank you for expanding on the proposal. A lot of it makes sense. My suggestions :
@melvincarvalho As much as I think it is important to discuss this, I need to ask you to remain factual.
Pretty much no server works reliably
That's is incorrect and unfair. All of the 401 bugs that appeared on the Gitter the past week have been resolved without any changes on the server code. If you find a bug in a server, please report it. In absence of such a report, we assume that servers work reliably.
None of our apps work with it
That is incorrect, and you are aware of that.
Yes, there are apps that don't work, because they rely on TLS. That's why we wrote solid-auth-client, they should simply use that.
Tooling (eg around bots & smart proxies) does not exist, is undocumented, and complex
Agreed, this needs improvement.
Creation of new apps is undocumented and impractical
This is incorrect:
This last part is feedback from several one on one sessions where new developers have tried to create hello world apps, and have given up as the bar is too high.
Please document this experience and have them report bugs. Have they started from the right documentation?
I have 50 second-year undergrads working on this based on the two pointers above, and none of them complained, so that's another datapoint.
I think the proposal can possibly be broken into parts
Will do.
@elf-pavlik
I see OIDC provider as very specific responsibility which not all solid servers, which support WebID-OIDC authenticated requests have to support as well.
Very good point. This should be an extra config option.
Maybe I misunderstand how solid implements it but I assume TLS client certs for WebID-TLS and Bearer tokens for WebID-OIDC.
In OIDC mode, a TLS client cert also results in an OIDC bearer token.
See https://github.com/solid/solid/issues/138#issuecomment-387439471
Does solid server support all those authentication mechanisms as part if its identity provider role, or it would also provide them for cases like one above (server accepts authenticated requests but does NOT act as OIDC provider)?
Yes, should be independent.
In OIDC mode, a TLS client cert also results in an OIDC bearer token.
Looking at https://github.com/solid/solid/issues/138#issuecomment-387439471 it looks that WebID-TLS only gets used with user's IDP, in that case https://my.solid/
Does it mean that this user will never use WebID-TLS with https://other.solid/ or any other server non acting as one's own IDP, and authentication with those other servers always uses OIDC barer token?
If so, a WebID-TLS only client doesn't seem able to do anything else than authenticate with users IDP, since everything else seems to rely on OIDC barer tokens. But that doesn't seem to fit one of your comments above
What
alwaysRequestClientCertadds is that WebID-TLS authentication can be applied to any resource, instead of having one special resource that handles auth (as is the case with the current OIDC mode).
I understand above as client having possibility to use WebID-TLS client cert and not relying on OIDC barer tokens.
BTW, does alwaysRequestClientCert only addresses need to trigger a certificate selection popup in the browser, or non browser clients (bots, smart proxies) would also require having it enabled?
I try to understand what implications it would have on a client which want to interact with servers no matter if they have alwaysRequestClientCert enabled or disabled.
Does solid server support all those authentication mechanisms as part if its identity provider role, or it would also provide them for cases like one above (server accepts authenticated requests but does NOT act as OIDC provider)?
Yes, should be independent.
How would username/password authentication with server other than my IDP work? Would that allow me to set such credentials for each orgin and later use them to get barer token or even cookie?
Following use case from the other issue, https://other.solid/ would allow me to set a password specific for that origin with my WebID https://me.solid/user#me and later use neither WebID-TLS or WebID-OIDC?
Apologies if I confuse things but I really want to clarify the distinction between solid server which acts as my OIDC provider and other solid servers which may only act as origins for datasets. While using username/password with my OIDC provider makes perfect sense for me, for all those non IDP origins using client certs with WebID-TLS and barer tokens with WebID-OIDC seems enough since WebID has to get verified at lest once even if after verifying it one would use username/password.
In OIDC mode, a TLS client cert also results in an OIDC bearer token.
Looking at solid/solid#138 (comment) it looks that WebID-TLS only gets used with user's IDP, in that case https://my.solid/
Well, yes and no, and it's actually good that you're pointing that out.
Because a POST with a client certificate to /login/tls on server A will actually create a cookie-based session with session A for the WebID in that certificate.
So you can POST to https://other.solid/login/tls to get logged in there with WebID-TLS.
Does it mean that this user will never use WebID-TLS with https://other.solid/ or any other server non acting as one's own IDP, and authentication with those other servers always uses OIDC barer token?
So that would be the case if we were doing pure OIDC.
Yet I guess we ended up with a mixture of different systems, which is the real problem here.
BTW, does alwaysRequestClientCert only addresses need to trigger a certificate selection popup in the browser, or non browser clients (bots, smart proxies) would also require having it enabled?
Bots would be free to send or not send a cert, just like the browser.
I try to understand what implications it would have on a client which want to interact with servers no matter if they have alwaysRequestClientCert enabled or disabled.
Would be easier to do plain curl if it's enabled. While that is a good argument (I love curl), I think we should have tooling that helps with the bearer token.
How would username/password authentication with server other than my IDP work?
It wouldn't.
Following use case from the other issue, https://other.solid/ would allow me to set a password specific for that origin with my WebID https://me.solid/user#me and later use neither WebID-TLS or WebID-OIDC?
That could be the case, but https://other.solid/ would need to be marked in https://me.solid/user#me as an identify provider. Then https://other.solid/ would be free to use _any_ mechanism, including different password, or fingerprint, …
Apologies if I confuse things but I really want to clarify the distinction between solid server which acts as my OIDC provider and other solid servers which may only act as origins for datasets.
You're right asking for clarity, and as you can see from above, the current implementation got many things mixed up.
Since this has become a discussion instead of the original issue, I'm transforming this to an actual discussion. I'm opening a new issue here: https://github.com/solid/node-solid-server/issues/672. The original issue is now a subpoint of a larger undertaking.
Thanks for your patience @RubenVerborgh :pray:
BTW, does alwaysRequestClientCert only addresses need to trigger a certificate selection popup in the browser, or non browser clients (bots, smart proxies) would also require having it enabled?
Bots would be free to send or not send a cert, just like the browser.
I try to understand what implications it would have on a client which want to interact with servers no matter if they have enabled or disabled.
Would be easier to do plain
curlif it's enabled. While that is a good argument (I lovecurl), I think we should have tooling that helps with the bearer token.
I understand that with alwaysRequestClientCert: false when using curl together with client cert, server would NOT use WebID-TLS to have request authenticated. I must admit not recalling all the nuances related to triggering cert selection popup in web browser, I thought alwaysRequestClientCert: true only ensures triggering that popup, and clients which have better control over including client certificate or not in the request (like curl) could still perform WebID-TLS authenticated requests on any resource even with alwaysRequestClientCert: false.
Yet I guess we ended up with a mixture of different systems, which is the real problem here.
If alwaysRequestClientCert: true would only come as requirement to trigger cert selection popup in web browser, and no matter of its setting server would use logic like
This would allow clients which can initiate WebID-TLS to use it if they choose so and all the rest would rely on WebID-OICD. From what I recall, assuming that servers will take care of forcing WebID-TLS just to trigger that unfortunate popup in a web browser tends to raise complexity quite a lot.
I understand that with alwaysRequestClientCert: false when using curl together with client cert, server would NOT use WebID-TLS to have request authenticated.
Indeed.
I thought alwaysRequestClientCert: true only ensures triggering that popup, and clients which have better control over including client certificate or not in the request (like curl) could still perform WebID-TLS authenticated requests on any resource even with alwaysRequestClientCert: false.
That does not seem to be the case.
This would allow clients which can initiate WebID-TLS to use it if they choose so and all the rest would rely on WebID-OICD.
Indeed.
Alternative option: https://github.com/solid/solid/issues/145
Following up in #672.
Most helpful comment
Well, yes and no, and it's actually good that you're pointing that out.
Because a POST with a client certificate to
/login/tlson server A will actually create a cookie-based session with session A for the WebID in that certificate.So you can POST to https://other.solid/login/tls to get logged in there with WebID-TLS.
So that would be the case if we were doing pure OIDC.
Yet I guess we ended up with a mixture of different systems, which is the real problem here.
Bots would be free to send or not send a cert, just like the browser.
Would be easier to do plain
curlif it's enabled. While that is a good argument (I lovecurl), I think we should have tooling that helps with the bearer token.It wouldn't.
That could be the case, but https://other.solid/ would need to be marked in https://me.solid/user#me as an identify provider. Then https://other.solid/ would be free to use _any_ mechanism, including different password, or fingerprint, …
You're right asking for clarity, and as you can see from above, the current implementation got many things mixed up.