I've written a proof-of-concept script which fetches a file from a protected svn repo, and posted it on the dev list <https://lists.apache.org/thread/f3f516vkm16ss67g9xfrjrfdcp70ymd0>. With a bit of luck, this might get someone interested in adding the OAuth2 code to svn and TSVN.

-Evan

On 30/03/2024 13:40, EML wrote:

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

Reply via email to