Subject: Re: bug#58985: 29.0.50; Have auth-source-pass behave more like other back ends

From: "J.P." <[email-masked]>
Date: Thu, 10 Nov 2022 06:40:08 -0800

Björn Bidar <[email-masked]> writes:

> "J.P." <[email-masked]> writes:
>
>> I know this is asking a lot, but if you get a chance, please apply the
>> v2 patches and try them out. (Actually, you can omit the second one in
>> the set, which only affects ERC.)
>
> I want to add I'm not an ERC user but circe user, I've got interested in
> the patch as I use the backend with circe, gnus, magit, elfeed and so
> on.

All great packages!

>>> will this mean the backend will act less like Passwordstore.org
>>> describes or more?
>>
>> That's a good question. My main goal thus far has been to make its query
>> behavior as close as possible to that of the other auth-source back
>> ends. Glancing at that web page, it seems auth-source-pass has taken
>> some liberties WRT to query features, like drilling down into the tail
>> of a file's contents and ascribing semantics to parts of a file name.
>
> A lot of programs don't implement the full path traversal and just end
> up having a static or a bogus path (e.g. those that implement
> Freedesktop SecretService with pass).

Interesting. I just blindly assumed auth-source-pass would be alone in
that regard, but I guess not in the slightest.

> So I favor a correct implementation, any progress is welcome.

I don't think correctness from the passwordstore.org perspective will
butt heads with auth-source's because only the latter has any concept of
host, user, and port. Although, as you've noticed, my patch only
addresses queries and doesn't handle writes, which may be a different
animal entirely.

>>> I think the backend should follow the users organization of the
>>> passwordstore folder if possible.
>>
>> From this I'll infer that the current implementation of auth-source-pass
>> does that sufficiently. If that's so and the changes I'm proposing
>> threaten to interfere with that, what's your opinion on the default
>> value of a knob to toggle the new behavior?
>
> Hm it depends if there are any backends that workaround that old behavior.
> From what I see the only difference really is that you can specify
> require and max.

There are actually a few subtle areas where the behavior between old and
new differs and maybe one or two slightly unintuitive gotchas for folks
unfamiliar with how the other back ends operate. If you're curious,
there's a series of side-by-side comparisons added by the first patch
toward the bottom of

  test/lisp/auth-source-pass-tests.el

Please let me know if you have any questions.

> My personal bindings for circe to auth-source currently only exist of
> small functions:
> ;; Adopted from Ghub.el, refactored for use with Circe IRC
> (defun circe--ident (username network)
>   (format "%s^%s" username network))
> (defun circe--auth-source-get (keys &rest spec)
>   (declare (indent 1))
>   (let ((plist (car (apply #'auth-source-search
>                            (append spec (list :max 1))))))
                                                ~~~~~~
                             ERC would choke on this ^

>     (mapcar (lambda (k)
>               (plist-get plist k))
>             keys)))
> (defun circe-pass-get (host user &optional network)
>   "\fn(fn host user &optional network)"
>   (auth-source-forget (list :host host :user user :max 1))
>   (when network
>     (setq user (circe--ident user network)))
>   (let ((match (car (circe--auth-source-get (list :secret)
>                       :host host :user user))))
>     (cond ((null match)
>            (error "Auth source empty for %s %s %s" host user network))
>           ((functionp match)
>            (funcall match)) (t match))))
>
>
> Which makes me wonder why ERC needs the different behavior but then I'm
> not really a good lisp programmer more a novice.

The approach is broadly similar to what you have. But ERC uses
auth-source to query server passwords, network credentials, and channel
keys more or less transparently, without user interaction. It overloads
both :host and :user to accommodate various values based on context and
doesn't rely on auth-source for narrowing. It asks for all applicable
results and does its own thing from there.