Hi Thomas/Daniel/etc. First, standard disclaimer: this isn't my day job,
and I'm still new to OIDC, so apologies if any of this is wrong/too
obvious/whatever. On your points:
(1) HTTP requests need to specify 'Authorization: Bearer' with an access
token.
Are you sure mod_openidc accepts a Bearer token when configured with AuthType
openid-connect?
openid-connect is the only OIDC AuthType (the AuthTypes aren't properly
documented, which doesn't help).
I think there may be some confusion here, though (TL;DR: bearer tokens
must be used, and not cookies).
Why? If I just use a browser to connect to an OAuth2-protected resource
which is on a server behind Apache/mod_auth_openidc ('MAO'), /then I
never need, or even see, a bearer token/. The reason is that this is
handled internally by MAO. When I first browse to a protected resource,
MAO sees that I don't have a session cookie, and connects to the
identity provider (which it normally finds from
'OIDCProviderMetadataURL'). MAO then pops ups a login window at the
provider (the 'IdP', ie. Google/github/whatever); the provider then
authenticates and redirects back to MAO. If this works out, MAO sends
back my requested page, /plus a session cookie/. My browser then uses
this session cookie to communicate with the server; it doesn't need the
bearer token.
/But/: this isn't how command-line access would work. Something (GCM,
for the sake of argument) connects /directly/ to the identity provider
(see the 'credential' section in my first post, which tells GCM how to
do this). GCM needs to talk to a 'client' at the IdP (more on this
below). It pops up a login window, goes through a token swap procedure,
and gets a JWT token if successful. GCM now has a token that it can use
to communicate with MAO on my server. This next bit I'm a bit hazy on,
because I've only done minimal testing with GCM. However, I presume that
MAO then uses the JWT from the browser to communicate back to the IdP to
check the token validity (or maybe it just uses the IdP's known public
key to decode the JWT, and then assumes that it's valid), and then sends
me back a session cookie, just like it does for normal web access.
Note, of course, that we cannot assume that the server with the
protected repo will be running MAO. Frameworks (Tomcat/etc) generally
have their own way to do this (but it's probably safe to assume that
most people who have an svn repo will use MAO). All we know for sure is
that the repo is OAuth2-protected (OIDC, to be precise), and we have to
use the OAuth2 specs. RFC6750
<https://datatracker.ietf.org/doc/html/rfc6750> says in the abstract
that "/This specification describes how to use bearer tokens in HTTP
requests to access OAuth 2.0 protected resources. Any party in
possession of a bearer token (a "bearer") can use it to get access to
the associated resources (without demonstrating possession of a
cryptographic key)./" So, bearer tokens must be used. You can put the
token in a cookie, but you then have to create an agreed name for that
cookie, and I can't imagine that anyone does that. I think the cookie
confusion is to do with session cookies.
However, I think this all pretty moot in out case, unless you/we/someone
intends to re-invent the wheel and write a version of
GCM/git-credential-oauth/oidc-agent/whatever. I've got some time today
and I'm going to try to install oidc-agent and connect through to a
protected svn repo. If I can come up with a 'manual' procedure then this
could be coded up in svn.
This is not the approach we have taken (*due to complexity and uncertainty related to protecting the app
registration client-secret*). We let mod_openidc handle as much complexity as possible.
The client secret is interesting. There are 2 client types
<https://datatracker.ietf.org/doc/html/rfc6749#section-2.1> defined in
the RFC: confidential, and public. They differ in how secure the client
credentials are (not the credentials of the user trying to log in; the
credentials the client app needs to talk to the OAuth server). You would
think that we're taking about a public client here: lots of people on
different computers are trying to access the repo, all using the same
app credentials. But, in fact, everyone's agreed that this sort of CLI
client, carrying out machine to machine (M2M) communication, is a
confidential client. This means that your app (the thing we're talking
about writing here, ie. 'oidc-svn'/whatever) must use a client secret to
talk to the OAuth server. The server uses this to determine whether the
app is authorised to talk to the API. This means that you have to suck
it up and protect the client secret. See this SO answer
<https://stackoverflow.com/a/57762140/785194> for tips (note that the
'HansZ' referred to is the author of MAO).
If you see my original .gitconfig in this thread you'll see that the
client secret is completely /un/protected - it is (or would be) in
cleartext in an easily accessible file. This is just a simple hard-wired
.gitconfig; I think (I'm not a git expert) I could set up the credential
store and use 'git config' to store the secret in a more secure way. In
any event, the issue here is that svn needs to store the secret in a
better way than in my example. If the secret is compromised, it can be
used to sign JWTs, and get access to the API. However, this may not be
as bad as it sounds: the client can be created at the OAuth2 server to
give it limited permissions (it only needs to authorise svn users, so
doesn't need admin functions). The redirect URI also gives good security.
-Evan