You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@serf.apache.org by Branko Čibej <br...@apache.org> on 2025/06/14 19:23:19 UTC

Thinking about MFA infrastructure

Hi all,

I've been digging into Serf's support for various authentication schemes 
and I notices something that looks like a bit of a limitation.

Unless I'm much mistaken, there's space for only one authentication 
baton in Serf's context. It would seem that this is rather a blocker for 
implementing multi-factor authentication flows, for example, Basic + 
OTP, where the server would first require basic credentials and then, if 
those were correct, go on to issue an OTP challenge.

It seems to me that a simple solution for that would be to store an 
authn baton per scheme, but I know on the close order of nothing about 
the possible side effects.

Yeah, I'm starting small, I have no wish to implement OAuth2 flow any 
time soon. Still, a bit of insight from the knowledgeable would be welcome.

-- Brane

Re: Thinking about MFA infrastructure

Posted by Branko Čibej <br...@apache.org>.
On 8. 7. 25 22:22, Dirk-Willem van Gulik wrote:
> On 8 Jul 2025, at 17:26, Branko Čibej<br...@apache.org>  wrote:
>> On 26. 6. 25 08:16, Branko Čibej wrote:
>>> On 24. 6. 25 07:52, Branko Čibej wrote:
>>>> On 14. 6. 25 21:23, Branko Čibej wrote:
>>>>> Hi all,
>>>>>
>>>>> I've been digging into Serf's support for various authentication schemes and I notices something that looks like a bit of a limitation.
>>>>>
>>>>> Unless I'm much mistaken, there's space for only one authentication baton in Serf's context. It would seem that this is rather a blocker for implementing multi-factor authentication flows, for example, Basic + OTP, where the server would first require basic credentials and then, if those were correct, go on to issue an OTP challenge.
>>>>>
>>>>> It seems to me that a simple solution for that would be to store an authn baton per scheme, but I know on the close order of nothing about the possible side effects.
>>>>>
>>>>> Yeah, I'm starting small, I have no wish to implement OAuth2 flow any time soon. Still, a bit of insight from the knowledgeable would be welcome.
>>>>
>>>> With r1926674, I think the user-defined-authn branch is ready for review. Here's a short summary of the changes on the branch:
>>>>
>>>>   * The (private) struct serf__authn_scheme_t, defined in auth/auth.h,
>>>>     grew a number of new members to support user-defined schemes, among
>>>>     them five new user-visible callback functions. These, along with
>>>>     their interactions, are described in serf.h. The built-in
>>>>     authentication schemes don't need or use these new members.
>>>>
>>>>   * The (private) table serf_authn_schemes, defined in auth/auth.c, has
>>>>     been extended to have room for as many schemes as there are bits in
>>>>     serf__authn_scheme_t::type. Locking was added to serialize access,
>>>>     because new schemes can be registered at runtime.
>>>>
>>>>   * Private callbacks were added to implement the user-visible
>>>>     authentication flow.
>>>>
>>>>   * Two new public APIs take care of registering and unregistering
>>>>     authentication schemes. The latter is tricky because we don't track
>>>>     references to the schemes in contexts and connections, only in the
>>>>     serf_authn_schemes table; this issue is documented.
>>>>
>>>>   * A number of tests were added for all this new stuff.
>>>>
>>>>
>>>> Please take a look if you have time.
>>>>
>>>>     svn diff --internal-diff \
>>>> https://svn.apache.org/repos/asf/serf/trunk   \
>>>> https://svn.apache.org/repos/asf/serf/branches/user-defined-authn  \
>>>>          | colordiff --color=always \
>>>>          | less -R
>>>>
>>> There are a couple more changes on that branch now:
>>>
>>>   * The parameters in the authentication challenge (headers
>>>     WWW-Authenticate and Proxy-Authenticate) are now parsed into a
>>>     dictionary, using the rules described in RFC 9110.
>>>
>>>   * The Authentication-Info and Proxy-Authentication-Info response
>>>     headers are now handled and their values parsed as above.
>>>
>>> These two changes should make life much easier for authn scheme implementers. I decided to add this once I saw how many times we have copy-pasted not-quite-compliant parsers throughout the auth code...
>>>
>>> (Note that these changes do not stop implementers from doing whatever wrong-headed, non-compliant horror they can think of, as all the raw information and headers are still available in the callbacks.)
>> Any takers? It's been a couple of weeks now. I'd sure like to get another pair of eyes on these changes before merging them to trunk, but I'd rather not have the branch fall victim to bitrot, either.
> I'll bite - so I've tried it against  some auth testing code we privately maintain for legacy hardware keys - and it certainly gets rid of a lot of the boilerplate/header parse code - without loss of functionality.  And oddly it passes now an EAGAIN/EINTR edge case that always broke our tests.
>
> Improvement overall.


Thanks for testing! This is encouraging.

-- Brane

Re: Thinking about MFA infrastructure

Posted by Daniel Sahlberg <da...@gmail.com>.
Den tis 8 juli 2025 kl 22:23 skrev Dirk-Willem van Gulik <
dirkx@webweaving.org>:

> On 8 Jul 2025, at 17:26, Branko Čibej <br...@apache.org> wrote:
> > On 26. 6. 25 08:16, Branko Čibej wrote:
> >> On 24. 6. 25 07:52, Branko Čibej wrote:
> >>> On 14. 6. 25 21:23, Branko Čibej wrote:
> >>>> Hi all,
> >>>>
> >>>> I've been digging into Serf's support for various authentication
> schemes and I notices something that looks like a bit of a limitation.
> >>>>
> >>>> Unless I'm much mistaken, there's space for only one authentication
> baton in Serf's context. It would seem that this is rather a blocker for
> implementing multi-factor authentication flows, for example, Basic + OTP,
> where the server would first require basic credentials and then, if those
> were correct, go on to issue an OTP challenge.
> >>>>
> >>>> It seems to me that a simple solution for that would be to store an
> authn baton per scheme, but I know on the close order of nothing about the
> possible side effects.
> >>>>
> >>>> Yeah, I'm starting small, I have no wish to implement OAuth2 flow any
> time soon. Still, a bit of insight from the knowledgeable would be welcome.
> >>>
> >>>
> >>> With r1926674, I think the user-defined-authn branch is ready for
> review. Here's a short summary of the changes on the branch:
> >>>
> >>>  * The (private) struct serf__authn_scheme_t, defined in auth/auth.h,
> >>>    grew a number of new members to support user-defined schemes, among
> >>>    them five new user-visible callback functions. These, along with
> >>>    their interactions, are described in serf.h. The built-in
> >>>    authentication schemes don't need or use these new members.
> >>>
> >>>  * The (private) table serf_authn_schemes, defined in auth/auth.c, has
> >>>    been extended to have room for as many schemes as there are bits in
> >>>    serf__authn_scheme_t::type. Locking was added to serialize access,
> >>>    because new schemes can be registered at runtime.
> >>>
> >>>  * Private callbacks were added to implement the user-visible
> >>>    authentication flow.
> >>>
> >>>  * Two new public APIs take care of registering and unregistering
> >>>    authentication schemes. The latter is tricky because we don't track
> >>>    references to the schemes in contexts and connections, only in the
> >>>    serf_authn_schemes table; this issue is documented.
> >>>
> >>>  * A number of tests were added for all this new stuff.
> >>>
> >>>
> >>> Please take a look if you have time.
> >>>
> >>>    svn diff --internal-diff \
> >>> https://svn.apache.org/repos/asf/serf/trunk  \
> >>> https://svn.apache.org/repos/asf/serf/branches/user-defined-authn \
> >>>         | colordiff --color=always \
> >>>         | less -R
> >>>
> >>
> >> There are a couple more changes on that branch now:
> >>
> >>  * The parameters in the authentication challenge (headers
> >>    WWW-Authenticate and Proxy-Authenticate) are now parsed into a
> >>    dictionary, using the rules described in RFC 9110.
> >>
> >>  * The Authentication-Info and Proxy-Authentication-Info response
> >>    headers are now handled and their values parsed as above.
> >>
> >> These two changes should make life much easier for authn scheme
> implementers. I decided to add this once I saw how many times we have
> copy-pasted not-quite-compliant parsers throughout the auth code...
> >>
> >> (Note that these changes do not stop implementers from doing whatever
> wrong-headed, non-compliant horror they can think of, as all the raw
> information and headers are still available in the callbacks.)
> >
> > Any takers? It's been a couple of weeks now. I'd sure like to get
> another pair of eyes on these changes before merging them to trunk, but I'd
> rather not have the branch fall victim to bitrot, either.
>
> I'll bite - so I've tried it against  some auth testing code we privately
> maintain for legacy hardware keys - and it certainly gets rid of a lot of
> the boilerplate/header parse code - without loss of functionality.  And
> oddly it passes now an EAGAIN/EINTR edge case that always broke our tests.
>
> Improvement overall.
>
> Dw


Thanks for testing! It is on my todo list to review it but it seems there
are always new issues / pr popping up and I've not been able to prioritise
this. My goal is to do it before the end of summer vacations...

/Daniel

Re: Thinking about MFA infrastructure

Posted by Dirk-Willem van Gulik <di...@webweaving.org>.
On 8 Jul 2025, at 17:26, Branko Čibej <br...@apache.org> wrote:
> On 26. 6. 25 08:16, Branko Čibej wrote:
>> On 24. 6. 25 07:52, Branko Čibej wrote:
>>> On 14. 6. 25 21:23, Branko Čibej wrote:
>>>> Hi all,
>>>> 
>>>> I've been digging into Serf's support for various authentication schemes and I notices something that looks like a bit of a limitation.
>>>> 
>>>> Unless I'm much mistaken, there's space for only one authentication baton in Serf's context. It would seem that this is rather a blocker for implementing multi-factor authentication flows, for example, Basic + OTP, where the server would first require basic credentials and then, if those were correct, go on to issue an OTP challenge.
>>>> 
>>>> It seems to me that a simple solution for that would be to store an authn baton per scheme, but I know on the close order of nothing about the possible side effects.
>>>> 
>>>> Yeah, I'm starting small, I have no wish to implement OAuth2 flow any time soon. Still, a bit of insight from the knowledgeable would be welcome.
>>> 
>>> 
>>> With r1926674, I think the user-defined-authn branch is ready for review. Here's a short summary of the changes on the branch:
>>> 
>>>  * The (private) struct serf__authn_scheme_t, defined in auth/auth.h,
>>>    grew a number of new members to support user-defined schemes, among
>>>    them five new user-visible callback functions. These, along with
>>>    their interactions, are described in serf.h. The built-in
>>>    authentication schemes don't need or use these new members.
>>> 
>>>  * The (private) table serf_authn_schemes, defined in auth/auth.c, has
>>>    been extended to have room for as many schemes as there are bits in
>>>    serf__authn_scheme_t::type. Locking was added to serialize access,
>>>    because new schemes can be registered at runtime.
>>> 
>>>  * Private callbacks were added to implement the user-visible
>>>    authentication flow.
>>> 
>>>  * Two new public APIs take care of registering and unregistering
>>>    authentication schemes. The latter is tricky because we don't track
>>>    references to the schemes in contexts and connections, only in the
>>>    serf_authn_schemes table; this issue is documented.
>>> 
>>>  * A number of tests were added for all this new stuff.
>>> 
>>> 
>>> Please take a look if you have time.
>>> 
>>>    svn diff --internal-diff \
>>> https://svn.apache.org/repos/asf/serf/trunk  \
>>> https://svn.apache.org/repos/asf/serf/branches/user-defined-authn \
>>>         | colordiff --color=always \
>>>         | less -R
>>> 
>> 
>> There are a couple more changes on that branch now:
>> 
>>  * The parameters in the authentication challenge (headers
>>    WWW-Authenticate and Proxy-Authenticate) are now parsed into a
>>    dictionary, using the rules described in RFC 9110.
>> 
>>  * The Authentication-Info and Proxy-Authentication-Info response
>>    headers are now handled and their values parsed as above.
>> 
>> These two changes should make life much easier for authn scheme implementers. I decided to add this once I saw how many times we have copy-pasted not-quite-compliant parsers throughout the auth code...
>> 
>> (Note that these changes do not stop implementers from doing whatever wrong-headed, non-compliant horror they can think of, as all the raw information and headers are still available in the callbacks.)
> 
> Any takers? It's been a couple of weeks now. I'd sure like to get another pair of eyes on these changes before merging them to trunk, but I'd rather not have the branch fall victim to bitrot, either.

I'll bite - so I've tried it against  some auth testing code we privately maintain for legacy hardware keys - and it certainly gets rid of a lot of the boilerplate/header parse code - without loss of functionality.  And oddly it passes now an EAGAIN/EINTR edge case that always broke our tests.

Improvement overall.

Dw

Re: Thinking about MFA infrastructure

Posted by Branko Čibej <br...@apache.org>.
On 8. 7. 25 17:26, Branko Čibej wrote:
> On 26. 6. 25 08:16, Branko Čibej wrote:
>> On 24. 6. 25 07:52, Branko Čibej wrote:
>>> On 14. 6. 25 21:23, Branko Čibej wrote:
>>>> Hi all,
>>>>
>>>> I've been digging into Serf's support for various authentication 
>>>> schemes and I notices something that looks like a bit of a limitation.
>>>>
>>>> Unless I'm much mistaken, there's space for only one authentication 
>>>> baton in Serf's context. It would seem that this is rather a 
>>>> blocker for implementing multi-factor authentication flows, for 
>>>> example, Basic + OTP, where the server would first require basic 
>>>> credentials and then, if those were correct, go on to issue an OTP 
>>>> challenge.
>>>>
>>>> It seems to me that a simple solution for that would be to store an 
>>>> authn baton per scheme, but I know on the close order of nothing 
>>>> about the possible side effects.
>>>>
>>>> Yeah, I'm starting small, I have no wish to implement OAuth2 flow 
>>>> any time soon. Still, a bit of insight from the knowledgeable would 
>>>> be welcome.
>>>
>>>
>>> With r1926674, I think the user-defined-authn branch is ready for 
>>> review. Here's a short summary of the changes on the branch:
>>>
>>>  * The (private) struct serf__authn_scheme_t, defined in auth/auth.h,
>>>    grew a number of new members to support user-defined schemes, among
>>>    them five new user-visible callback functions. These, along with
>>>    their interactions, are described in serf.h. The built-in
>>>    authentication schemes don't need or use these new members.
>>>
>>>  * The (private) table serf_authn_schemes, defined in auth/auth.c, has
>>>    been extended to have room for as many schemes as there are bits in
>>>    serf__authn_scheme_t::type. Locking was added to serialize access,
>>>    because new schemes can be registered at runtime.
>>>
>>>  * Private callbacks were added to implement the user-visible
>>>    authentication flow.
>>>
>>>  * Two new public APIs take care of registering and unregistering
>>>    authentication schemes. The latter is tricky because we don't track
>>>    references to the schemes in contexts and connections, only in the
>>>    serf_authn_schemes table; this issue is documented.
>>>
>>>  * A number of tests were added for all this new stuff.
>>>
>>>
>>> Please take a look if you have time.
>>>
>>>    svn diff --internal-diff \
>>> https://svn.apache.org/repos/asf/serf/trunk  \
>>> https://svn.apache.org/repos/asf/serf/branches/user-defined-authn \
>>>         | colordiff --color=always \
>>>         | less -R
>>>
>>
>> There are a couple more changes on that branch now:
>>
>>  * The parameters in the authentication challenge (headers
>>    WWW-Authenticate and Proxy-Authenticate) are now parsed into a
>>    dictionary, using the rules described in RFC 9110.
>>
>>  * The Authentication-Info and Proxy-Authentication-Info response
>>    headers are now handled and their values parsed as above.
>>
>> These two changes should make life much easier for authn scheme 
>> implementers. I decided to add this once I saw how many times we have 
>> copy-pasted not-quite-compliant parsers throughout the auth code...
>>
>> (Note that these changes do not stop implementers from doing whatever 
>> wrong-headed, non-compliant horror they can think of, as all the raw 
>> information and headers are still available in the callbacks.)
>
>
> Any takers? It's been a couple of weeks now. I'd sure like to get 
> another pair of eyes on these changes before merging them to trunk, 
> but I'd rather not have the branch fall victim to bitrot, either.

After a month of waiting for feedback, I decided to merge this branch to 
trunk in r1927627. All my testing on several platforms has not shown any 
problems.

-- Brane

Re: Thinking about MFA infrastructure

Posted by Branko Čibej <br...@apache.org>.
On 26. 6. 25 08:16, Branko Čibej wrote:
> On 24. 6. 25 07:52, Branko Čibej wrote:
>> On 14. 6. 25 21:23, Branko Čibej wrote:
>>> Hi all,
>>>
>>> I've been digging into Serf's support for various authentication 
>>> schemes and I notices something that looks like a bit of a limitation.
>>>
>>> Unless I'm much mistaken, there's space for only one authentication 
>>> baton in Serf's context. It would seem that this is rather a blocker 
>>> for implementing multi-factor authentication flows, for example, 
>>> Basic + OTP, where the server would first require basic credentials 
>>> and then, if those were correct, go on to issue an OTP challenge.
>>>
>>> It seems to me that a simple solution for that would be to store an 
>>> authn baton per scheme, but I know on the close order of nothing 
>>> about the possible side effects.
>>>
>>> Yeah, I'm starting small, I have no wish to implement OAuth2 flow 
>>> any time soon. Still, a bit of insight from the knowledgeable would 
>>> be welcome.
>>
>>
>> With r1926674, I think the user-defined-authn branch is ready for 
>> review. Here's a short summary of the changes on the branch:
>>
>>  * The (private) struct serf__authn_scheme_t, defined in auth/auth.h,
>>    grew a number of new members to support user-defined schemes, among
>>    them five new user-visible callback functions. These, along with
>>    their interactions, are described in serf.h. The built-in
>>    authentication schemes don't need or use these new members.
>>
>>  * The (private) table serf_authn_schemes, defined in auth/auth.c, has
>>    been extended to have room for as many schemes as there are bits in
>>    serf__authn_scheme_t::type. Locking was added to serialize access,
>>    because new schemes can be registered at runtime.
>>
>>  * Private callbacks were added to implement the user-visible
>>    authentication flow.
>>
>>  * Two new public APIs take care of registering and unregistering
>>    authentication schemes. The latter is tricky because we don't track
>>    references to the schemes in contexts and connections, only in the
>>    serf_authn_schemes table; this issue is documented.
>>
>>  * A number of tests were added for all this new stuff.
>>
>>
>> Please take a look if you have time.
>>
>>    svn diff --internal-diff \
>> https://svn.apache.org/repos/asf/serf/trunk  \
>> https://svn.apache.org/repos/asf/serf/branches/user-defined-authn \
>>         | colordiff --color=always \
>>         | less -R
>>
>
> There are a couple more changes on that branch now:
>
>  * The parameters in the authentication challenge (headers
>    WWW-Authenticate and Proxy-Authenticate) are now parsed into a
>    dictionary, using the rules described in RFC 9110.
>
>  * The Authentication-Info and Proxy-Authentication-Info response
>    headers are now handled and their values parsed as above.
>
> These two changes should make life much easier for authn scheme 
> implementers. I decided to add this once I saw how many times we have 
> copy-pasted not-quite-compliant parsers throughout the auth code...
>
> (Note that these changes do not stop implementers from doing whatever 
> wrong-headed, non-compliant horror they can think of, as all the raw 
> information and headers are still available in the callbacks.)


Any takers? It's been a couple of weeks now. I'd sure like to get 
another pair of eyes on these changes before merging them to trunk, but 
I'd rather not have the branch fall victim to bitrot, either.

-- Brane

Re: Thinking about MFA infrastructure

Posted by Branko Čibej <br...@apache.org>.
On 24. 6. 25 07:52, Branko Čibej wrote:
> On 14. 6. 25 21:23, Branko Čibej wrote:
>> Hi all,
>>
>> I've been digging into Serf's support for various authentication 
>> schemes and I notices something that looks like a bit of a limitation.
>>
>> Unless I'm much mistaken, there's space for only one authentication 
>> baton in Serf's context. It would seem that this is rather a blocker 
>> for implementing multi-factor authentication flows, for example, 
>> Basic + OTP, where the server would first require basic credentials 
>> and then, if those were correct, go on to issue an OTP challenge.
>>
>> It seems to me that a simple solution for that would be to store an 
>> authn baton per scheme, but I know on the close order of nothing 
>> about the possible side effects.
>>
>> Yeah, I'm starting small, I have no wish to implement OAuth2 flow any 
>> time soon. Still, a bit of insight from the knowledgeable would be 
>> welcome.
>
>
> With r1926674, I think the user-defined-authn branch is ready for 
> review. Here's a short summary of the changes on the branch:
>
>  * The (private) struct serf__authn_scheme_t, defined in auth/auth.h,
>    grew a number of new members to support user-defined schemes, among
>    them five new user-visible callback functions. These, along with
>    their interactions, are described in serf.h. The built-in
>    authentication schemes don't need or use these new members.
>
>  * The (private) table serf_authn_schemes, defined in auth/auth.c, has
>    been extended to have room for as many schemes as there are bits in
>    serf__authn_scheme_t::type. Locking was added to serialize access,
>    because new schemes can be registered at runtime.
>
>  * Private callbacks were added to implement the user-visible
>    authentication flow.
>
>  * Two new public APIs take care of registering and unregistering
>    authentication schemes. The latter is tricky because we don't track
>    references to the schemes in contexts and connections, only in the
>    serf_authn_schemes table; this issue is documented.
>
>  * A number of tests were added for all this new stuff.
>
>
> Please take a look if you have time.
>
>    svn diff --internal-diff \
> https://svn.apache.org/repos/asf/serf/trunk  \
> https://svn.apache.org/repos/asf/serf/branches/user-defined-authn \
>         | colordiff --color=always \
>         | less -R
>

There are a couple more changes on that branch now:

  * The parameters in the authentication challenge (headers
    WWW-Authenticate and Proxy-Authenticate) are now parsed into a
    dictionary, using the rules described in RFC 9110.

  * The Authentication-Info and Proxy-Authentication-Info response
    headers are now handled and their values parsed as above.

These two changes should make life much easier for authn scheme 
implementers. I decided to add this once I saw how many times we have 
copy-pasted not-quite-compliant parsers throughout the auth code...

(Note that these changes do not stop implementers from doing whatever 
wrong-headed, non-compliant horror they can think of, as all the raw 
information and headers are still available in the callbacks.)

-- Brane

Re: Thinking about MFA infrastructure

Posted by Peter Balogh <pe...@svnplus.com>.
Hi,

This seems to be exactly what I need, I'll continue working on the 
integration, and let you know if I get stuck :)
Thanks

Best regards,
Peter

On 2025. 06. 24. 14:58, Peter Balogh wrote:
>
> Hi,
>
> Awesome, thank you! :)
> I'll see if I can fire up my svn 2FA PoC using this in a few days
>
> Best regards,
> Peter
> On 2025. 06. 24. 7:52, Branko Čibej wrote:
>> On 14. 6. 25 21:23, Branko Čibej wrote:
>>> Hi all,
>>>
>>> I've been digging into Serf's support for various authentication 
>>> schemes and I notices something that looks like a bit of a limitation.
>>>
>>> Unless I'm much mistaken, there's space for only one authentication 
>>> baton in Serf's context. It would seem that this is rather a blocker 
>>> for implementing multi-factor authentication flows, for example, 
>>> Basic + OTP, where the server would first require basic credentials 
>>> and then, if those were correct, go on to issue an OTP challenge.
>>>
>>> It seems to me that a simple solution for that would be to store an 
>>> authn baton per scheme, but I know on the close order of nothing 
>>> about the possible side effects.
>>>
>>> Yeah, I'm starting small, I have no wish to implement OAuth2 flow 
>>> any time soon. Still, a bit of insight from the knowledgeable would 
>>> be welcome.
>>
>>
>> With r1926674, I think the user-defined-authn branch is ready for 
>> review. Here's a short summary of the changes on the branch:
>>
>>   * The (private) struct serf__authn_scheme_t, defined in
>>     auth/auth.h, grew a number of new members to support user-defined
>>     schemes, among them five new user-visible callback functions.
>>     These, along with their interactions, are described in serf.h.
>>     The built-in authentication schemes don't need or use these new
>>     members.
>>
>>   * The (private) table serf_authn_schemes, defined in auth/auth.c,
>>     has been extended to have room for as many schemes as there are
>>     bits in serf__authn_scheme_t::type. Locking was added to
>>     serialize access, because new schemes can be registered at runtime.
>>
>>   * Private callbacks were added to implement the user-visible
>>     authentication flow.
>>
>>   * Two new public APIs take care of registering and unregistering
>>     authentication schemes. The latter is tricky because we don't
>>     track references to the schemes in contexts and connections, only
>>     in the serf_authn_schemes table; this issue is documented.
>>
>>   * A number of tests were added for all this new stuff.
>>
>>
>> Please take a look if you have time.
>>
>>     svn diff --internal-diff \
>>          https://svn.apache.org/repos/asf/serf/trunk \
>>          https://svn.apache.org/repos/asf/serf/branches/user-defined-authn \
>>          | colordiff --color=always \
>>          | less -R
>>
>>
>> -- Brane
>>

Re: Thinking about MFA infrastructure

Posted by Peter Balogh <pe...@svnplus.com>.
Hi,

Awesome, thank you! :)
I'll see if I can fire up my svn 2FA PoC using this in a few days

Best regards,
Peter

On 2025. 06. 24. 7:52, Branko Čibej wrote:
> On 14. 6. 25 21:23, Branko Čibej wrote:
>> Hi all,
>>
>> I've been digging into Serf's support for various authentication 
>> schemes and I notices something that looks like a bit of a limitation.
>>
>> Unless I'm much mistaken, there's space for only one authentication 
>> baton in Serf's context. It would seem that this is rather a blocker 
>> for implementing multi-factor authentication flows, for example, 
>> Basic + OTP, where the server would first require basic credentials 
>> and then, if those were correct, go on to issue an OTP challenge.
>>
>> It seems to me that a simple solution for that would be to store an 
>> authn baton per scheme, but I know on the close order of nothing 
>> about the possible side effects.
>>
>> Yeah, I'm starting small, I have no wish to implement OAuth2 flow any 
>> time soon. Still, a bit of insight from the knowledgeable would be 
>> welcome.
>
>
> With r1926674, I think the user-defined-authn branch is ready for 
> review. Here's a short summary of the changes on the branch:
>
>   * The (private) struct serf__authn_scheme_t, defined in auth/auth.h,
>     grew a number of new members to support user-defined schemes,
>     among them five new user-visible callback functions. These, along
>     with their interactions, are described in serf.h. The built-in
>     authentication schemes don't need or use these new members.
>
>   * The (private) table serf_authn_schemes, defined in auth/auth.c,
>     has been extended to have room for as many schemes as there are
>     bits in serf__authn_scheme_t::type. Locking was added to serialize
>     access, because new schemes can be registered at runtime.
>
>   * Private callbacks were added to implement the user-visible
>     authentication flow.
>
>   * Two new public APIs take care of registering and unregistering
>     authentication schemes. The latter is tricky because we don't
>     track references to the schemes in contexts and connections, only
>     in the serf_authn_schemes table; this issue is documented.
>
>   * A number of tests were added for all this new stuff.
>
>
> Please take a look if you have time.
>
>     svn diff --internal-diff \
>          https://svn.apache.org/repos/asf/serf/trunk \
>          https://svn.apache.org/repos/asf/serf/branches/user-defined-authn \
>          | colordiff --color=always \
>          | less -R
>
>
> -- Brane
>

Re: Thinking about MFA infrastructure

Posted by Daniel Sahlberg <da...@gmail.com>.
Den tis 24 juni 2025 kl 07:52 skrev Branko Čibej <br...@apache.org>:

> With r1926674, I think the user-defined-authn branch is ready for
> review. Here's a short summary of the changes on the branch:
>

[...]

Thanks for the hard work so far!

I will try to take a look but I won't be able to allocate any meaningful
time until earliest during the weekend.

Cheers,
Daniel

Re: Thinking about MFA infrastructure

Posted by Branko Čibej <br...@apache.org>.
On 14. 6. 25 21:23, Branko Čibej wrote:
> Hi all,
>
> I've been digging into Serf's support for various authentication 
> schemes and I notices something that looks like a bit of a limitation.
>
> Unless I'm much mistaken, there's space for only one authentication 
> baton in Serf's context. It would seem that this is rather a blocker 
> for implementing multi-factor authentication flows, for example, Basic 
> + OTP, where the server would first require basic credentials and 
> then, if those were correct, go on to issue an OTP challenge.
>
> It seems to me that a simple solution for that would be to store an 
> authn baton per scheme, but I know on the close order of nothing about 
> the possible side effects.
>
> Yeah, I'm starting small, I have no wish to implement OAuth2 flow any 
> time soon. Still, a bit of insight from the knowledgeable would be 
> welcome.


With r1926674, I think the user-defined-authn branch is ready for 
review. Here's a short summary of the changes on the branch:

  * The (private) struct serf__authn_scheme_t, defined in auth/auth.h,
    grew a number of new members to support user-defined schemes, among
    them five new user-visible callback functions. These, along with
    their interactions, are described in serf.h. The built-in
    authentication schemes don't need or use these new members.

  * The (private) table serf_authn_schemes, defined in auth/auth.c, has
    been extended to have room for as many schemes as there are bits in
    serf__authn_scheme_t::type. Locking was added to serialize access,
    because new schemes can be registered at runtime.

  * Private callbacks were added to implement the user-visible
    authentication flow.

  * Two new public APIs take care of registering and unregistering
    authentication schemes. The latter is tricky because we don't track
    references to the schemes in contexts and connections, only in the
    serf_authn_schemes table; this issue is documented.

  * A number of tests were added for all this new stuff.


Please take a look if you have time.

    svn diff --internal-diff \
         https://svn.apache.org/repos/asf/serf/trunk  \
         https://svn.apache.org/repos/asf/serf/branches/user-defined-authn  \
         | colordiff --color=always \
         | less -R


-- Brane

Re: Thinking about MFA infrastructure

Posted by Branko Čibej <br...@apache.org>.
On 23. 9. 25 09:14, Peter Balogh wrote:
> On 7/20/2025 2:55 AM, Branko Čibej wrote:
>> [please do not top-post]
>> On 19. 7. 25 23:50, Peter Balogh wrote:
>>> Hi,
>>>
>>> So you’re generally you have no objection to the idea, that I 
>>> recreate the whole Basic auth implementation in svn to support a 
>>> custom Basic+OTP auth scheme?
>>
>>
>> Why are you asking about Subversion here? That's another mailing 
>> list, you should discuss that there.
>>
>>
>> The point of multi-factor authorisation is that each identifying 
>> factor comes from a different place. Some Basic+OTP authentication 
>> scheme isn't MFA, and the client will have to keep sending the same 
>> info (possibly with an updated OTP token) on every request. That 
>> would probably involve using some kind of bearer token. I think the 
>> place to start is here: https://www.rfc-editor.org/rfc/rfc9110, 
>> section 11, and design a scheme that at the very least does not 
>> require sending the username+password on every request. the 
>> Authentication-Info response header (11.6.3) may turn out to be 
>> useful here. And at that point it might make sense to look closely at 
>> OAuth2 again. Who knows, maybe it can be made to work without 
>> requiring a browser. -- Brane
>>> On Thu, Jul 17, 2025, at 15:05, Branko Čibej wrote:
>>>> On 14. 7. 25 01:01, Peter Balogh wrote:
>>>>> Hi,
>>>>>
>>>>> I think I've just run into this,
>>>>>
>>>>> Here's the current flow:
>>>>> 1st request without auth gets a 401 response with WWW-Authenticate:
>>>>> Digest header
>>>>> 2nd request sent with Authorization header gets a WWW-Authenticate:
>>>>> MFA headaer
>>>>> 3rd request is sent with OTP, but this goes without Authorization: 
>>>>> Digest
>>>>> In my current implementation the user's password is rerequested, and
>>>>> everything works fine after that, but I'm having trouble fixing this
>>>> As I already wrote elsewhere, Serf handles only one authentication
>>>> method per realm. And that's correct, because it turns out that the 
>>>> RFC
>>>> requires it to be so.
>>>>
>>>>
>>>>> I can probably add an auth method that does both Basic+OTP, but it'd
>>>>> probably mean code duplication, or calling the Basic auth method
>>>>> functions from the new method,
>>>> Not without hacking Serf's internals directly. The user-defined-authn
>>>> code doesn't give you access to those, on purpose.
>>>>
>>>>> but these feel wrong
>>>>>
>>>>> Any pointers, how to move this forward?
>>>>>
>>>>> Best regards,
>>>>> Peter
>>>>>
>>>>> On 2025. 06. 14. 21:23, Branko Čibej wrote:
>>>>>> Hi all,
>>>>>>
>>>>>> I've been digging into Serf's support for various authentication
>>>>>> schemes and I notices something that looks like a bit of a 
>>>>>> limitation.
>>>>>>
>>>>>> Unless I'm much mistaken, there's space for only one authentication
>>>>>> baton in Serf's context. It would seem that this is rather a blocker
>>>>>> for implementing multi-factor authentication flows, for example,
>>>>>> Basic + OTP, where the server would first require basic credentials
>>>>>> and then, if those were correct, go on to issue an OTP challenge.
>>>>>>
>>>>>> It seems to me that a simple solution for that would be to store an
>>>>>> authn baton per scheme, but I know on the close order of nothing
>>>>>> about the possible side effects.
>>>>>>
>>>>>> Yeah, I'm starting small, I have no wish to implement OAuth2 flow 
>>>>>> any
>>>>>> time soon. Still, a bit of insight from the knowledgeable would be
>>>>>> welcome.
>>>>>>
>>>>>> -- Brane
>>>>>>
>>
> Hi,
>
> I wanted to give a quick update of my progress in the last couple 
> months, partially to share the current plan for feedback, and 
> partially to have a written log of how I got to the server side of MFA.
> The initial idea was that after a successful Basic / Digest auth 
> request, the server would still return a 401, but with a different 
> Auth method

Keep in mind that once an authorisation method succeeds, you must from 
then on always send the Authorization header for that method with 
requests. Serf does that automagically,  as long as the authn scheme 
code is written correctly.


> The current svn/serf implementation poses a problem, because after the 
> auth response, in the subsequent requests, the Authorization header 
> will not be presented, as that auth method did not succeed
> That makes properly setting the user on the server side a difficult task.

Invalid Authorization headers (those that did not produce a successful 
response) must not be repeated in requests. In other words, whatever you 
send to the server must contain all the information required for 
authenticating a request. In your case, you'll have to somehow send the 
username along with whichever second factor you choose.


> Initially I tried using mod rewrite, but I have not found a way to set 
> a username that way
> I've tried implementing an AuthBasicProvider script, but that doesn't 
> trigger in case there's no Authorization header
> I've finally found mod_lua, and LuaHookAccessChecker seems to be on 
> the correct path, so I'll be implementing the MFA server side using 
> this route

The server must not cache raw credentials. What it can do is return an 
Authentication-Info response that contains, e.g., an access token to 
present for subsequent requests, and the client then takes care of 
constructing the correct Authorization header. The cache is then on the 
client side, the server only validates the token. A JWT for example 
contains all relevant info, without exposing passwords, even encrypted, 
on the 'net. Something like a TOTP code can't be part of the JWT, but 
can be safely sent in a separate authn parameter, since it's a one-time 
code that can't be spoofed in a repeat attack, especially when paired 
with a token with a unique nonce.

-- Brane

Re: Thinking about MFA infrastructure

Posted by Peter Balogh <pe...@svnplus.com>.
On 7/20/2025 2:55 AM, Branko Čibej wrote:
> [please do not top-post]
> On 19. 7. 25 23:50, Peter Balogh wrote:
>> Hi,
>>
>> So you’re generally you have no objection to the idea, that I 
>> recreate the whole Basic auth implementation in svn to support a 
>> custom Basic+OTP auth scheme?
>
>
> Why are you asking about Subversion here? That's another mailing list, 
> you should discuss that there.
>
>
> The point of multi-factor authorisation is that each identifying 
> factor comes from a different place. Some Basic+OTP authentication 
> scheme isn't MFA, and the client will have to keep sending the same 
> info (possibly with an updated OTP token) on every request. That would 
> probably involve using some kind of bearer token. I think the place to 
> start is here: https://www.rfc-editor.org/rfc/rfc9110, section 11, and 
> design a scheme that at the very least does not require sending the 
> username+password on every request. the Authentication-Info response 
> header (11.6.3) may turn out to be useful here. And at that point it 
> might make sense to look closely at OAuth2 again. Who knows, maybe it 
> can be made to work without requiring a browser. -- Brane
>> On Thu, Jul 17, 2025, at 15:05, Branko Čibej wrote:
>>> On 14. 7. 25 01:01, Peter Balogh wrote:
>>>> Hi,
>>>>
>>>> I think I've just run into this,
>>>>
>>>> Here's the current flow:
>>>> 1st request without auth gets a 401 response with WWW-Authenticate:
>>>> Digest header
>>>> 2nd request sent with Authorization header gets a WWW-Authenticate:
>>>> MFA headaer
>>>> 3rd request is sent with OTP, but this goes without Authorization: 
>>>> Digest
>>>> In my current implementation the user's password is rerequested, and
>>>> everything works fine after that, but I'm having trouble fixing this
>>> As I already wrote elsewhere, Serf handles only one authentication
>>> method per realm. And that's correct, because it turns out that the RFC
>>> requires it to be so.
>>>
>>>
>>>> I can probably add an auth method that does both Basic+OTP, but it'd
>>>> probably mean code duplication, or calling the Basic auth method
>>>> functions from the new method,
>>> Not without hacking Serf's internals directly. The user-defined-authn
>>> code doesn't give you access to those, on purpose.
>>>
>>>> but these feel wrong
>>>>
>>>> Any pointers, how to move this forward?
>>>>
>>>> Best regards,
>>>> Peter
>>>>
>>>> On 2025. 06. 14. 21:23, Branko Čibej wrote:
>>>>> Hi all,
>>>>>
>>>>> I've been digging into Serf's support for various authentication
>>>>> schemes and I notices something that looks like a bit of a 
>>>>> limitation.
>>>>>
>>>>> Unless I'm much mistaken, there's space for only one authentication
>>>>> baton in Serf's context. It would seem that this is rather a blocker
>>>>> for implementing multi-factor authentication flows, for example,
>>>>> Basic + OTP, where the server would first require basic credentials
>>>>> and then, if those were correct, go on to issue an OTP challenge.
>>>>>
>>>>> It seems to me that a simple solution for that would be to store an
>>>>> authn baton per scheme, but I know on the close order of nothing
>>>>> about the possible side effects.
>>>>>
>>>>> Yeah, I'm starting small, I have no wish to implement OAuth2 flow any
>>>>> time soon. Still, a bit of insight from the knowledgeable would be
>>>>> welcome.
>>>>>
>>>>> -- Brane
>>>>>
>
Hi,

I wanted to give a quick update of my progress in the last couple 
months, partially to share the current plan for feedback, and partially 
to have a written log of how I got to the server side of MFA.
The initial idea was that after a successful Basic / Digest auth 
request, the server would still return a 401, but with a different Auth 
method
The current svn/serf implementation poses a problem, because after the 
auth response, in the subsequent requests, the Authorization header will 
not be presented, as that auth method did not succeed
That makes properly setting the user on the server side a difficult task.
Initially I tried using mod rewrite, but I have not found a way to set a 
username that way
I've tried implementing an AuthBasicProvider script, but that doesn't 
trigger in case there's no Authorization header
I've finally found mod_lua, and LuaHookAccessChecker seems to be on the 
correct path, so I'll be implementing the MFA server side using this route

Let me know if you have any insight or comments to this approach

Best regards,
Peter

Re: Thinking about MFA infrastructure

Posted by Branko Čibej <br...@apache.org>.
[please do not top-post]
On 19. 7. 25 23:50, Peter Balogh wrote:
> Hi,
>
> So you’re generally you have no objection to the idea, that I recreate the whole Basic auth implementation in svn to support a custom Basic+OTP auth scheme?


Why are you asking about Subversion here? That's another mailing list, 
you should discuss that there.


The point of multi-factor authorisation is that each identifying factor 
comes from a different place. Some Basic+OTP authentication scheme isn't 
MFA, and the client will have to keep sending the same info (possibly 
with an updated OTP token) on every request. That would probably involve 
using some kind of bearer token. I think the place to start is here: 
https://www.rfc-editor.org/rfc/rfc9110, section 11, and design a scheme 
that at the very least does not require sending the username+password on 
every request. the Authentication-Info response header (11.6.3) may turn 
out to be useful here. And at that point it might make sense to look 
closely at OAuth2 again. Who knows, maybe it can be made to work without 
requiring a browser. -- Brane
> On Thu, Jul 17, 2025, at 15:05, Branko Čibej wrote:
>> On 14. 7. 25 01:01, Peter Balogh wrote:
>>> Hi,
>>>
>>> I think I've just run into this,
>>>
>>> Here's the current flow:
>>> 1st request without auth gets a 401 response with WWW-Authenticate:
>>> Digest header
>>> 2nd request sent with Authorization header gets a WWW-Authenticate:
>>> MFA headaer
>>> 3rd request is sent with OTP, but this goes without Authorization: Digest
>>> In my current implementation the user's password is rerequested, and
>>> everything works fine after that, but I'm having trouble fixing this
>> As I already wrote elsewhere, Serf handles only one authentication
>> method per realm. And that's correct, because it turns out that the RFC
>> requires it to be so.
>>
>>
>>> I can probably add an auth method that does both Basic+OTP, but it'd
>>> probably mean code duplication, or calling the Basic auth method
>>> functions from the new method,
>> Not without hacking Serf's internals directly. The user-defined-authn
>> code doesn't give you access to those, on purpose.
>>
>>> but these feel wrong
>>>
>>> Any pointers, how to move this forward?
>>>
>>> Best regards,
>>> Peter
>>>
>>> On 2025. 06. 14. 21:23, Branko Čibej wrote:
>>>> Hi all,
>>>>
>>>> I've been digging into Serf's support for various authentication
>>>> schemes and I notices something that looks like a bit of a limitation.
>>>>
>>>> Unless I'm much mistaken, there's space for only one authentication
>>>> baton in Serf's context. It would seem that this is rather a blocker
>>>> for implementing multi-factor authentication flows, for example,
>>>> Basic + OTP, where the server would first require basic credentials
>>>> and then, if those were correct, go on to issue an OTP challenge.
>>>>
>>>> It seems to me that a simple solution for that would be to store an
>>>> authn baton per scheme, but I know on the close order of nothing
>>>> about the possible side effects.
>>>>
>>>> Yeah, I'm starting small, I have no wish to implement OAuth2 flow any
>>>> time soon. Still, a bit of insight from the knowledgeable would be
>>>> welcome.
>>>>
>>>> -- Brane
>>>>

Re: Thinking about MFA infrastructure

Posted by Peter Balogh <pe...@svnplus.com>.
Hi,

So you’re generally you have no objection to the idea, that I recreate the whole Basic auth implementation in svn to support a custom Basic+OTP auth scheme?

Best regards,
Peter

On Thu, Jul 17, 2025, at 15:05, Branko Čibej wrote:
> On 14. 7. 25 01:01, Peter Balogh wrote:
> > Hi,
> >
> > I think I've just run into this,
> >
> > Here's the current flow:
> > 1st request without auth gets a 401 response with WWW-Authenticate: 
> > Digest header
> > 2nd request sent with Authorization header gets a WWW-Authenticate: 
> > MFA headaer
> > 3rd request is sent with OTP, but this goes without Authorization: Digest
> > In my current implementation the user's password is rerequested, and 
> > everything works fine after that, but I'm having trouble fixing this
> 
> As I already wrote elsewhere, Serf handles only one authentication 
> method per realm. And that's correct, because it turns out that the RFC 
> requires it to be so.
> 
> 
> > I can probably add an auth method that does both Basic+OTP, but it'd 
> > probably mean code duplication, or calling the Basic auth method 
> > functions from the new method,
> 
> Not without hacking Serf's internals directly. The user-defined-authn 
> code doesn't give you access to those, on purpose.
> 
> > but these feel wrong
> >
> > Any pointers, how to move this forward?
> >
> > Best regards,
> > Peter
> >
> > On 2025. 06. 14. 21:23, Branko Čibej wrote:
> >> Hi all,
> >>
> >> I've been digging into Serf's support for various authentication 
> >> schemes and I notices something that looks like a bit of a limitation.
> >>
> >> Unless I'm much mistaken, there's space for only one authentication 
> >> baton in Serf's context. It would seem that this is rather a blocker 
> >> for implementing multi-factor authentication flows, for example, 
> >> Basic + OTP, where the server would first require basic credentials 
> >> and then, if those were correct, go on to issue an OTP challenge.
> >>
> >> It seems to me that a simple solution for that would be to store an 
> >> authn baton per scheme, but I know on the close order of nothing 
> >> about the possible side effects.
> >>
> >> Yeah, I'm starting small, I have no wish to implement OAuth2 flow any 
> >> time soon. Still, a bit of insight from the knowledgeable would be 
> >> welcome.
> >>
> >> -- Brane
> >>
> 

Re: Thinking about MFA infrastructure

Posted by Branko Čibej <br...@apache.org>.
On 14. 7. 25 01:01, Peter Balogh wrote:
> Hi,
>
> I think I've just run into this,
>
> Here's the current flow:
> 1st request without auth gets a 401 response with WWW-Authenticate: 
> Digest header
> 2nd request sent with Authorization header gets a WWW-Authenticate: 
> MFA headaer
> 3rd request is sent with OTP, but this goes without Authorization: Digest
> In my current implementation the user's password is rerequested, and 
> everything works fine after that, but I'm having trouble fixing this

As I already wrote elsewhere, Serf handles only one authentication 
method per realm. And that's correct, because it turns out that the RFC 
requires it to be so.


> I can probably add an auth method that does both Basic+OTP, but it'd 
> probably mean code duplication, or calling the Basic auth method 
> functions from the new method,

Not without hacking Serf's internals directly. The user-defined-authn 
code doesn't give you access to those, on purpose.

> but these feel wrong
>
> Any pointers, how to move this forward?
>
> Best regards,
> Peter
>
> On 2025. 06. 14. 21:23, Branko Čibej wrote:
>> Hi all,
>>
>> I've been digging into Serf's support for various authentication 
>> schemes and I notices something that looks like a bit of a limitation.
>>
>> Unless I'm much mistaken, there's space for only one authentication 
>> baton in Serf's context. It would seem that this is rather a blocker 
>> for implementing multi-factor authentication flows, for example, 
>> Basic + OTP, where the server would first require basic credentials 
>> and then, if those were correct, go on to issue an OTP challenge.
>>
>> It seems to me that a simple solution for that would be to store an 
>> authn baton per scheme, but I know on the close order of nothing 
>> about the possible side effects.
>>
>> Yeah, I'm starting small, I have no wish to implement OAuth2 flow any 
>> time soon. Still, a bit of insight from the knowledgeable would be 
>> welcome.
>>
>> -- Brane
>>

Re: Thinking about MFA infrastructure

Posted by Peter Balogh <pe...@svnplus.com>.
Hi,

I think I've just run into this,

Here's the current flow:
1st request without auth gets a 401 response with WWW-Authenticate: 
Digest header
2nd request sent with Authorization header gets a WWW-Authenticate: MFA 
headaer
3rd request is sent with OTP, but this goes without Authorization: Digest
In my current implementation the user's password is rerequested, and 
everything works fine after that, but I'm having trouble fixing this

I can probably add an auth method that does both Basic+OTP, but it'd 
probably mean code duplication, or calling the Basic auth method 
functions from the new method, but these feel wrong

Any pointers, how to move this forward?

Best regards,
Peter

On 2025. 06. 14. 21:23, Branko Čibej wrote:
> Hi all,
>
> I've been digging into Serf's support for various authentication 
> schemes and I notices something that looks like a bit of a limitation.
>
> Unless I'm much mistaken, there's space for only one authentication 
> baton in Serf's context. It would seem that this is rather a blocker 
> for implementing multi-factor authentication flows, for example, Basic 
> + OTP, where the server would first require basic credentials and 
> then, if those were correct, go on to issue an OTP challenge.
>
> It seems to me that a simple solution for that would be to store an 
> authn baton per scheme, but I know on the close order of nothing about 
> the possible side effects.
>
> Yeah, I'm starting small, I have no wish to implement OAuth2 flow any 
> time soon. Still, a bit of insight from the knowledgeable would be 
> welcome.
>
> -- Brane
>