12

I have a Mercurial keyring on my Windows 7 machine. I am using the Python keyring library to get user credentials from the Mercurial keyring.

I can retrieve the password for a given username with:

keyring.get_password('Mercurial', 'user@@etc')

Is there a similar function to retrieve the username?

5 Answers 5

13

On Windows I was able to get both username and password (i.e. the "credentials") using

c = keyring.get_credential("servicename", None)

Note that this does not work on macOS, the keyring backend does not have capabilities to search for entries - i.e. you need to know the username. I suppose that native code would allow you to do this, though, see official docs

Sign up to request clarification or add additional context in comments.

4 Comments

Worth mentioning that you can access the username, password like so: c.username and c.password.
This is the most accurate answer.
Worth specifying get_credential is available from Keyring 15.2.0 onwards.
Why the official documentation does not say this?
12

As of Keyring 15.2.0, you can use keyring.get_credential to store a username and password together. The original answer has been kept below for reference.


While keyring was only designed to store passwords, you can abuse get_password to store the username separately.

import keyring

# store username & password
keyring.set_password("name_of_app", "username", "user123")
keyring.set_password("name_of_app", "password", "pass123")

# retrieve username & password
username = keyring.get_password("name_of_app", "username")
password = keyring.get_password("name_of_app", "password")

Alternatively, if you want to keep the username paired with the password:

import keyring

service_id = "name_of_app"
username = "user123"

# store username & password
keyring.set_password(service_id, "username", username)
keyring.set_password(service_id, username, "pass123")

# retrieve username & password
username = keyring.get_password(service_id, "username")
password = keyring.get_password(service_id, username)

Credit to Dustin Wyatt & Alex Chan for this solution.

2 Comments

Is the key (not the password) stored securely in the keychain or does that "paired" solution expose the username?
@DylanYoung This depends on the backend. Pass for example stores the credentials as a path.So the username is part of that path and only the credential file is encrypted.
7

You are expected to have stored the username somewhere else.

The keyring only stores the password, keyed by the application name and username.

Comments

5

You can retrieve a username with the get_credential function added in keyring 15.2.0.

import keyring

# Store credentials
keyring.set_password("service_name", "username", "password")

# Retrieve credentials
credentials = keyring.get_credential("service_name", None)
if credentials is not None:
    username = credentials.username
    password = credentials.password

Credit to MShekow and Eelco van Villet for providing a similar answer

Comments

3

If you want to hide your username in the script as well you can use credentials of the keyring module. Also I would recommend to use the getpass library for the input of the password; this prevents the password to be printed to screen. Finally, you may want to have a delete credentials somewhere in your code as soon as you notice that the login failed. Otherwise the script restart without the prompt to the user. As a full example. Here is how you would retrieve the username and password

import getpass
import keyring
import requests

service_name = "Name of the keyring"
credentials = keyring.get_credential(service_name, None)
if credentials is None:
    username = input("Username: ")
    password = getpass.getpass()
    keyring.set_password(service_name,username, password)
else:
    username = credentials.username
    password = credentials.password

Then you can do your thing, for instance do a post using request to an api. If it fails, delete the keyring to force to ask the credenitials again.

response = requests.post('url_to_api', auth=requests.auth.HTTPBasicAuth(username, password))
try:
    response.raise_for_status()
except requests.exceptions.HTTPError as err:
    keyring.delete_password(service_name, username)
    raise

If the login succeeds, the next time you don't have to input username and password again.

1 Comment

This response is elegant!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.