Node-solid-server: Discussion on TLS-only auth mode

Created on 8 May 2018  Â·  28Comments  Â·  Source: solid/node-solid-server

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:

  • username/password
  • client certificate (WebID-TLS through renegotiation)

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

authentication discussion

Most helpful comment

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.

All 28 comments

I'll respond to this issue with caution as religious wars on this topic have slowed down development.

What I'll say is that

  • node-solid-server in TLS mode is something I use on a daily basis
  • I would support documenting the short comings and finding where improvements can be made

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.

  1. 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.

  2. 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://solidtest.space/register

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?

Conceptual config structure

So imagine the configuration conceptually as follows:

{
  auth: {
    askClientCertOnEveryRequest: bool,
    oidc: {
        enabled: bool,
        usernamePassword: bool,
        clientCert: bool,
    }
  }
}

Meaning of auth: "tls"

Given the above, the meaning of auth: "tls" is:

{
  auth: {
    askClientCertOnEveryRequest: true,
    oidc: {
        enabled: false
    }
  }
}

Meaning of auth: "oidc"

Given the above, the meaning of auth: "oidc" is:

{
  auth: {
    askClientCertOnEveryRequest: false,
    oidc: {
        enabled: true,
        usernamePassword: true,
        clientCert: true,
    }
  }
}

What I propose

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.

What we could create instead

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:

  • clients which only use WebID-TLS (eg. bots, smart proxies)
  • clients which only use WebID-OIDC (eg. in browser apps)

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:

  • Both TLS and OIDC can be used by browser apps, bots, smart proxies. One requires more effort than the other at the moment, but tooling can remedy all of that.
  • OIDC provides both username/password and WebID-TLS login (and can provide more in the future).

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

  • NOT act as OIDC provider
  • support WebID-OIDC authenticated requests (various other servers would act as OIDC providers, never this one)
  • support WebID-TLS authenticated requests

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 :

  • Pretty much no server works reliably
  • None of our apps work with it
  • Tooling (eg around bots & smart proxies) does not exist, is undocumented, and complex
  • Creation of new apps is undocumented and impractical

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 :

  • A lot of progress in this issue, we should think about capturing the proposal more concretely
  • I think the proposal can possibly be broken into parts
  • Pushback will be reduced if it does not break existing working functionality with WebID-TLS

@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 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).

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 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.

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

  • if request includes client certificate use WebID-TLS
  • if request includes bearer token use WebID-OICD
  • else use WebID-OICD

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.

Following up in #672.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

WhyINeedToFillUsername picture WhyINeedToFillUsername  Â·  3Comments

melvincarvalho picture melvincarvalho  Â·  7Comments

kjetilk picture kjetilk  Â·  7Comments

csarven picture csarven  Â·  6Comments

ludwigschubi picture ludwigschubi  Â·  3Comments