0

Hi I'm attempting to utilize the Secret Service to access secrets in Gnome Keyring.

Everything works ok if the collection I'm trying to access is already unlocked. The problem I'm running into is when the collection/secrets are locked and it needs to prompt for the user to input their password to unlock it.

According to the docs

Operations that require a prompt to complete will return a prompt object. The client application must then call the Prompt() method of the prompt object to display the prompt. Client applications can use the window-id argument to display the prompt attached to their application window.

The Prompt() method is supposed to exist within org.freedesktop.Secret.Prompt per the docs.

I'm using D-Feet to try to find that, but nothing matching that name shows up in either the Session or System bus.

enter image description here

enter image description here

Any idea if this has moved? Or if I should be doing something else to display the prompt?

Thanks!

Jeremy Farmer
  • 425
  • 4
  • 14
  • Do you get given the prompt object by some other operation? I'm assuming that if you do an operation that requires the user to login then it return the prompt D-Bus object for you to use. Is that not what's happening? – ukBaz Nov 02 '22 at 07:28
  • Right, org.freedesktop.Secret.Service has a function "Unlock" that returns an ObjectPath for the prompt. Which I believe I'm supposed to provide to the Prompt method in org.freedesktop.Secret.Prompt though I could be entirely wrong there... I'm using C# so the function I'm calling looks like Task<(ObjectPath[] unlocked, ObjectPath prompt)> UnlockAsync(ObjectPath[] Objects); – Jeremy Farmer Nov 02 '22 at 22:36

1 Answers1

1

The test I've done was using the create a new collection functionality as I found this the method that was easy to do that issued a prompt.

There are two object paths returned from CreateCollection

collection

The new collection object, or '/' if prompting is necessary. 

prompt

A prompt object if prompting is necessary, or '/' if no prompt was needed.

I then used the prompt object to call the Prompt method with a random window ID. I waited for the prompt Completed signal before continuing.

A screenshot of the prompt:

Prompt from secrets

From the comments I can see you are using C#, unfortunately I don't know that so I have done my tests in Python. I'm hoping there is enough similarity to help move you forward.

from pydbus import SessionBus
from gi.repository import GLib

properties = {"org.freedesktop.Secret.Collection.Label": GLib.Variant.new_string("MyCollection")}

ses_bus = SessionBus()
service_name = 'org.freedesktop.secrets'
secret_service = ses_bus.get(service_name, '/org/freedesktop/secrets')

mainloop = GLib.MainLoop()


def _received_pw(dismissed, object_path):
    print("dismissed?", dismissed, object_path)
    mainloop.quit()


def show_prompt(prompt_id):
    prompt = ses_bus.get(service_name, prompt_id)
    prompt.onCompleted = _received_pw
    prompt.Prompt("random_id_for_window")
    mainloop.run()
    print('Prompt closed')


def add_my_collection():
    result = secret_service.CreateCollection(properties, "")
    print("result from CreateCollection", result)
    if result[1] != '/':
        show_prompt(result[1])


def remove_my_collection():
    for test_collect in secret_service.Collections:
        if "MyCollection" in test_collect:
            this_collection = ses_bus.get(service_name, test_collect)
            result = this_collection.Delete()
            if result != '/':
                show_prompt(result)


def main():
    add_my_collection()
    remove_my_collection()


if __name__ == '__main__':
    main()

Which gave the output:

result from CreateCollection ('/', '/org/freedesktop/secrets/prompt/p1')
dismissed? False /org/freedesktop/secrets/collection/MyCollection
Prompt closed

I've been using busctl to monitor what has been created. For example:

$ busctl --user tree org.freedesktop.secrets 
└─/org
  ├─/org/freedesktop
  │ ├─/org/freedesktop/portal
  │ │ └─/org/freedesktop/portal/desktop
  │ └─/org/freedesktop/secrets
  │   ├─/org/freedesktop/secrets/collection
  │   │ ├─/org/freedesktop/secrets/collection/MyCollection
  │   │ ├─/org/freedesktop/secrets/collection/login
  │   │ │ ├─/org/freedesktop/secrets/collection/login/1
  │   │ └─/org/freedesktop/secrets/collection/session
  │   ├─/org/freedesktop/secrets/prompt
  │   │ ├─/org/freedesktop/secrets/prompt/p1
  │   │ └─/org/freedesktop/secrets/prompt/u2
  │   └─/org/freedesktop/secrets/session
  │     ├─/org/freedesktop/secrets/session/s1
  └─/org/gnome
    └─/org/gnome/keyring
      └─/org/gnome/keyring/daemon

ukBaz
  • 6,985
  • 2
  • 8
  • 31
  • Thanks, this got me to the right answer, had to do a little extra with the library I'm using in C# to get the Prompt interface generated but everything worked after that! For anyone in the future using Tmds.Dbus for this - https://github.com/tmds/Tmds.DBus/issues/175 – Jeremy Farmer Nov 06 '22 at 01:14