Snapcraft authentication options

Snapcraft’s login credentials can be exported and subsequently used on a system where login is not possible or desired, such as on a system that’s offline. For cases when the system does not have a functioning or compatible keyring, Snapcraft will fall back to a file based backend.

Export snapcraft's login credentials

To export snapcraft’s login credentials, use the export-login command with the name of a file to store the credentials. On any system where Snapcraft is supported, run:

snapcraft export-login <credentials-filename>

You will be asked for your email, password and second-factor authentication.

Credentials exported with Snapcraft 7 can only be used with Snapcraft 7 or greater

Using exported snapcraft credentials

Previously exported credentials can be used to authenticate Snapcraft with an environment variable, or on older versions of Snapcraft, by using login --with and an external file.

SNAPCRAFT_STORE_CREDENTIALS environment variable

On the system you wish to use previously exported credentials, the contents of the credentials file needs to be placed into an environment variable called SNAPCRAFT_STORE_CREDENTIALS. This can be accomplished in many ways, but the following is a good solution:

export SNAPCRAFT_STORE_CREDENTIALS=$(cat <credentials-filename>)

Verifying accepted credentials

Use snapcraft whoami to verify login credentials are working:

$ snapcraft whoami
email: <account-email>
username: <account-name>
id: <account-id>
permissions: package_access, package_manage, package_metrics, 
package_push, package_register, package_release, package_update
channels: no restrictions
expires: 2023-06-15T14:49:49.000Z  
Legacy

Using exported snapcraft credentials

Deprecated:

Only supported for the migration from Snapcraft 6 to 7 when using credentials generated with Snapcraft 6

In addition to what is described in Using exported snapcraft credentials, the snapcraft login command accepts an additional --with argument to reference a login credentials file.

snapcraft login --with <credentials-filename>

Using a keyring on a headless Linux system

Deprecated:

Not required from Snapcraft 7.5.4 and onwards, Snapcraft will fallback to a file based backend in the absence of a working system keyring.

A Linux desktop will typically include an integrated keyring utility to store and retrieve passwords. This process can also be made to work on a headless system with no display connected or accessible desktop.

First, make sure gnome-keyring is installed:

apt install gnome-keyring

Now start a dbus session:

dbus-run-session -- sh 

To unlock the keyring from the command-line, run the following. You will be asked to enter a passphrase, type ctrl+d when done:

gnome-keyring-daemon --unlock

Now you can login as usual:

snapcraft login

Hi, I’m getting the following error:

craft-store error: Credentials could not be parsed. Expected base64 encoded credentials.

When echo "$SNAPCRAFT_STORE_CREDENTIALS", the output is the same as the file <credentials-filename>.

I’ve just tried this with snapcraft latest/stable 7.0.6 2022-06-16 (7710) and it works for me. I did snapcraft logout first, and then the ENV credentials just worked.

The contents of the credentials file/variable really is just a large block of base64 encoded text with no metadata.

$ printenv SNAPCRAFT_STORE_CREDENTIALS
eyJyIjogIk1EQXlPV3h2WTJGMGFXOXVJRzE1WVhCWm1sbGNpQ[...]

I did encounter a problem with snapcraft export-login , however, which now returns the following error after entering the password:

snapcraft output
Traceback (most recent call last):
  File "/snap/snapcraft/7710/bin/snapcraft", line 8, in <module>
    sys.exit(run())
  File "/snap/snapcraft/7710/lib/python3.8/site-packages/snapcraft/cli.py", line 181, in run
    dispatcher.run()
  File "/snap/snapcraft/7710/lib/python3.8/site-packages/craft_cli/dispatcher.py", line 406, in run
    return self._loaded_command.run(self._parsed_command_args)
  File "/snap/snapcraft/7710/lib/python3.8/site-packages/snapcraft/commands/account.py", line 217, in run
    credentials = store.StoreClientCLI(ephemeral=True).login(**kwargs)
  File "/snap/snapcraft/7710/lib/python3.8/site-packages/snapcraft/commands/store/client.py", line 187, in login
    credentials = self.store_client.login(
  File "/snap/snapcraft/7710/lib/python3.8/site-packages/snapcraft/commands/store/_legacy_account.py", line 149, in login
    raise NotImplementedError("Cannot login with legacy")
NotImplementedError: Cannot login with legacy

After reverting to snapcraft 7.0.5 export-login worked again.

1 Like

I can confirm that snapcraft export-login fails with NotImplementedError: Cannot login with legacy in snapcraft 7.0.6, and that reverting to 7.0.5 fixes the problem.

1 Like

I think I did export the login just before the install of the version 7.x was done… Because the login file was like:

[login.ubuntu.com]
macaroon = 
unbound_discharge = 
email =

I was able to export and whoami with the version 7.0.6 and 7.0.7.

Breaking so many existing workflows with no warning for people who publish snaps is unacceptable. At the very least I would expect existing workflows using $SNAPCRAFT_LOGIN with a reasonable expiry date (<1 year) to continue for working for a while. I’ve dropped support for snaps in my project for now. Hopefully snapcraft will be more developer-friendly in the future.

This is unfortunate, 7.0.6 should work with no changes

I see what is going on there; in order to preserve existing workflows, we added a check to see if the plain text credentials were on the file system and loaded another implementation for how credentials are managed, this takes precedence when exporting too; for now, snapcraft logout would clear those credentials and allow you to export (fix upcoming).

1 Like

With v7.0.7 available, reverting to v7.0.5 is no longer an option. I was able to work around this with snap refresh snapcraft --channel=6.x/stable

This should be fixed in 7.0.8 now on latest/candidate and 7.x/candidate

I will be posting small asciinema videos during the course of tomorrow (Friday) on all the login scenarios. Since 7.0.6 we addionally supported “login --with” but since then I saw folks use the “login --with” value with the new environment variable, so added a new code path to support that scenario as well.

1 Like

A couple of things to add @degville

Snapcraft 7 login --with using exported credentials from Snapcraft 6

asciicast

Snapcraft 7 login --with using exported credentials from Snapcraft 6

asciicast

Snapcraft 7 register-key

asciicast

1 Like

I’ll add them - thanks for the excellent demos!

If I am running 22.04, and I start some 22.04 LXD containers which I want to use as snapcraft build containers, should I do an independent “export-login” and credentials file creation, both on my host and in each LXD container, so that they all have distinct credentials? Or would it be sufficient to do that once on my host, then just share that credentials file with each LXD container?

I’ve just tested this and the credentials are identical with each export (at least currently), so it seems sharing credentials is sufficient.

It was totally unacceptable to ONLY find out it was going on when we had to install a new instance of services, you guys SHOULD HAVE NOTIFIED it in a better way like keeping this new login procedure as a future option while showing a deprecating message on the actual usage and later on transition to it in a more organised and professional way. Now we have a whole ecosystem of developers having all sort of problems for snapping and doing their job. And this weird and silly behaviour of turning a FORUM into a documentation is nothing but amateur, since we can not trust on everything we read and sometimes it is really difficult to distinguish between what is good and what is bad. I am totally frustrated, this is not what a linux community should be about.

Hm, login not working for me. In snapcarft 7.1.4 still not fixed.

Deployer# snapcraft login 
Cannot login with 'SNAPCRAFT_STORE_CREDENTIALS' set.                           
Recommended resolution: Unset 'SNAPCRAFT_STORE_CREDENTIALS' and try again.     
Full execution log: '/root/.cache/snapcraft/log/snapcraft-20221018-182645.670336.log'                                                                          
root@linuxHostBuildersUbuntu20:~/worker/cmake/LinuxCMakeBuilderQt6/QuasarApp/CQtDeployer# snapcraft --version 
snapcraft 7.1.4  

Full log

root@linuxHostBuildersUbuntu20:~/worker/cmake/LinuxCMakeBuilderQt6/QuasarApp/CQtDeployer# cat /root/.cache/snapcraft/log/snapcraft-20221018-182645.670336.log
2022-10-18 18:26:45.673 Starting Snapcraft 7.1.4
2022-10-18 18:26:45.678 Storing credentials for 'snapcraft' on 'dashboard.snapcraft.io' in keyring 'auth MemoryKeyring'.
2022-10-18 18:26:45.678 Cannot login with 'SNAPCRAFT_STORE_CREDENTIALS' set.
2022-10-18 18:26:45.679 Recommended resolution: Unset 'SNAPCRAFT_STORE_CREDENTIALS' and try again.
2022-10-18 18:26:45.679 Full execution log: '/root/.cache/snapcraft/log/snapcraft-20221018-182645.670336.log'
root@linuxHostBuildersUbuntu20:~/worker/cmake/LinuxCMakeBuilderQt6/QuasarApp/CQtDeployer# 

Note

I deploy on my build machine inner the lxd container

Hi, just tried with latest snapcraft 7.x, for me it is still working only with this:

Mind trying Snapcraft 7.2.0; the error message should at least be different and helpful for this situation; 7.2.0 is currently on candidate

1 Like

In clean ubuntu:20.04 and ubuntu:22.04 lxd containers, using snapcraft 7.2.10 (revision 8674) the “Using a keyring on a headless Linux system” instructions do not work. In the fresh container, after installing snapcraft I initially get

ubuntu@snapcraft-login-test-3:~$ snapcraft login
craft-store error: No keyring found to store or retrieve credentials from.                                                                                                       
Recommended resolution: Ensure the keyring is working or SNAPCRAFT_STORE_CREDENTIALS is correctly exported into the environment                                                  
For more information, check out: https://snapcraft.io/docs/snapcraft-authentication                                                                                              
Full execution log: '/home/ubuntu/.cache/snapcraft/log/snapcraft-20230125-203430.755481.log' 

as you would expect. I then install gnome-keyring. Then running

ubuntu@snapcraft-login-test-3:~$ dbus-run-session -- sh
$ gnome-keyring-daemon --unlock

gives no output at all, instead of prompting for a passphrase. I can then do one of two things, each which gives the same result: 1) I can leave the above command hanging and open a new shell in the same LXD container or 2) I can just press ctrl+D, which drops me back into my dbus-run-session -- sh shell.

In either scenario, when I then try to run snapcraft login, I get the normal prompt for my email, enter it, get a prompt for my password, enter it and press enter, and then snapcraft throws an exception and I get a whole bunch of stacktraces, as seen below:

ubuntu@snapcraft-login-test-3:~$ snapcraft login
Enter your Ubuntu One e-mail address and password.                                                                                                                               
If you do not have an Ubuntu One account, you can create one at https://snapcraft.io/account                                                                                     
Email: <redacting my email>
Password: 
Traceback (most recent call last):
  File "/snap/snapcraft/8674/lib/python3.8/site-packages/secretstorage/util.py", line 48, in send_and_get_reply
    raise DBusErrorResponse(resp_msg)
jeepney.wrappers.DBusErrorResponse: [org.freedesktop.DBus.Error.UnknownMethod] ('No such interface “org.freedesktop.DBus.Properties” on object at path /org/freedesktop/secrets/collection/login',)

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/snap/snapcraft/8674/lib/python3.8/site-packages/secretstorage/collection.py", line 177, in get_default_collection
    return Collection(connection)
  File "/snap/snapcraft/8674/lib/python3.8/site-packages/secretstorage/collection.py", line 45, in __init__
    self._collection.get_property('Label')
  File "/snap/snapcraft/8674/lib/python3.8/site-packages/secretstorage/util.py", line 67, in get_property
    (signature, value), = self.send_and_get_reply(msg)
  File "/snap/snapcraft/8674/lib/python3.8/site-packages/secretstorage/util.py", line 52, in send_and_get_reply
    raise ItemNotFoundException('Item does not exist!') from resp
secretstorage.exceptions.ItemNotFoundException: Item does not exist!

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/snap/snapcraft/8674/lib/python3.8/site-packages/keyring/backends/SecretService.py", line 61, in get_preferred_collection
    collection = secretstorage.get_default_collection(bus)
  File "/snap/snapcraft/8674/lib/python3.8/site-packages/secretstorage/collection.py", line 179, in get_default_collection
    return create_collection(connection, 'Default', 'default', session)
  File "/snap/snapcraft/8674/lib/python3.8/site-packages/secretstorage/collection.py", line 159, in create_collection
    raise PromptDismissedException('Prompt dismissed.')
secretstorage.exceptions.PromptDismissedException: Prompt dismissed.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/snap/snapcraft/8674/bin/snapcraft", line 8, in <module>
    sys.exit(run())
  File "/snap/snapcraft/8674/lib/python3.8/site-packages/snapcraft/cli.py", line 228, in run
    _run_dispatcher(dispatcher)
  File "/snap/snapcraft/8674/lib/python3.8/site-packages/snapcraft/cli.py", line 204, in _run_dispatcher
    dispatcher.run()
  File "/snap/snapcraft/8674/lib/python3.8/site-packages/craft_cli/dispatcher.py", line 448, in run
    return self._loaded_command.run(self._parsed_command_args)
  File "/snap/snapcraft/8674/lib/python3.8/site-packages/snapcraft/commands/account.py", line 113, in run
    store.StoreClientCLI().login()
  File "/snap/snapcraft/8674/lib/python3.8/site-packages/snapcraft/store/client.py", line 216, in login
    credentials = self.store_client.login(
  File "/snap/snapcraft/8674/lib/python3.8/site-packages/craft_store/base_client.py", line 130, in login
    self._auth.ensure_no_credentials()
  File "/snap/snapcraft/8674/lib/python3.8/site-packages/craft_store/auth.py", line 131, in ensure_no_credentials
    if self._keyring.get_password(self.application_name, self.host) is not None:
  File "/snap/snapcraft/8674/lib/python3.8/site-packages/keyring/backends/SecretService.py", line 78, in get_password
    collection = self.get_preferred_collection()
  File "/snap/snapcraft/8674/lib/python3.8/site-packages/keyring/backends/SecretService.py", line 63, in get_preferred_collection
    raise InitError("Failed to create the collection: %s." % e)
keyring.errors.InitError: Failed to create the collection: Prompt dismissed..

Alternatively, if (similarly to the first route above) I leave gnome-keyring-daemon --unlock hanging in the first shell and open a new shell in the same lxd container but instead of directly running snapcraft login I run dbus-run-session -- sh and then snapcraft login, I get the following, with the stacktrace only coming after 2 minutes of nothing

ubuntu@snapcraft-login-test-3:~$ dbus-run-session -- sh
$ snapcraft login
dbus-daemon[3014]: [session uid=1000 pid=3014] Activating service name='org.freedesktop.systemd1' requested by ':1.0' (uid=1000 pid=3016 comm="snapcraft login " label="unconfined")
dbus-daemon[3014]: [session uid=1000 pid=3014] Activated service 'org.freedesktop.systemd1' failed: Process org.freedesktop.systemd1 exited with status 1
Enter your Ubuntu One e-mail address and password.                                                                                                                               
If you do not have an Ubuntu One account, you can create one at https://snapcraft.io/account                                                                                     
Email: <redacting my email>
Password: 
dbus-daemon[3014]: [session uid=1000 pid=3014] Activating service name='org.freedesktop.secrets' requested by ':1.5' (uid=1000 pid=3016 comm="/snap/snapcraft/8674/bin/python /snap/snapcraft/86" label="snap.snapcraft.snapcraft (complain)")
SSH_AUTH_SOCK=/run/user/1000/keyring/ssh
dbus-daemon[3014]: [session uid=1000 pid=3014] Failed to activate service 'org.freedesktop.secrets': timed out (service_start_timeout=120000ms)
Traceback (most recent call last):
  File "/snap/snapcraft/8674/bin/snapcraft", line 8, in <module>
    sys.exit(run())
  File "/snap/snapcraft/8674/lib/python3.8/site-packages/snapcraft/cli.py", line 228, in run
    _run_dispatcher(dispatcher)
  File "/snap/snapcraft/8674/lib/python3.8/site-packages/snapcraft/cli.py", line 204, in _run_dispatcher
    dispatcher.run()
  File "/snap/snapcraft/8674/lib/python3.8/site-packages/craft_cli/dispatcher.py", line 448, in run
    return self._loaded_command.run(self._parsed_command_args)
  File "/snap/snapcraft/8674/lib/python3.8/site-packages/snapcraft/commands/account.py", line 113, in run
    store.StoreClientCLI().login()
  File "/snap/snapcraft/8674/lib/python3.8/site-packages/snapcraft/store/client.py", line 216, in login
    credentials = self.store_client.login(
  File "/snap/snapcraft/8674/lib/python3.8/site-packages/craft_store/base_client.py", line 130, in login
    self._auth.ensure_no_credentials()
  File "/snap/snapcraft/8674/lib/python3.8/site-packages/craft_store/auth.py", line 131, in ensure_no_credentials
    if self._keyring.get_password(self.application_name, self.host) is not None:
  File "/snap/snapcraft/8674/lib/python3.8/site-packages/keyring/backends/SecretService.py", line 78, in get_password
    collection = self.get_preferred_collection()
  File "/snap/snapcraft/8674/lib/python3.8/site-packages/keyring/backends/SecretService.py", line 61, in get_preferred_collection
    collection = secretstorage.get_default_collection(bus)
  File "/snap/snapcraft/8674/lib/python3.8/site-packages/secretstorage/collection.py", line 177, in get_default_collection
    return Collection(connection)
  File "/snap/snapcraft/8674/lib/python3.8/site-packages/secretstorage/collection.py", line 45, in __init__
    self._collection.get_property('Label')
  File "/snap/snapcraft/8674/lib/python3.8/site-packages/secretstorage/util.py", line 67, in get_property
    (signature, value), = self.send_and_get_reply(msg)
  File "/snap/snapcraft/8674/lib/python3.8/site-packages/secretstorage/util.py", line 48, in send_and_get_reply
    raise DBusErrorResponse(resp_msg)
jeepney.wrappers.DBusErrorResponse: [org.freedesktop.DBus.Error.TimedOut] ("Failed to activate service 'org.freedesktop.secrets': timed out (service_start_timeout=120000ms)",)
$ 

Also, as a nitpick it looks like there’s an extra closed parenthesis in the hyperlinks at the top of the post

Could you verify if running eval $(echo password | gnome-keyring-daemon --daemonize --unlock) inside the dbus session shell and before running snapcraft login works for you? When you run it with --unlock it waits for the password in stdin.