Skip to main content

OTP on the Linux command line

Using SMS as a two-factor authentication method is quite a bad idea. Bruce Schneier agrees with NIST, saying that it should no longer have any place in a 2FA environment. The UK's National Cyber Security Centre NCSC also does not recommend this.

MFA USB Token

While this was initially a novelty, it has lately started to grate on me that each application and service has their own secure key and authentication method. They each have their own physical 2FA keys. Once a user has to carry around multiple 2FA tokens around, weariness will settle in and they will compromise on security.

To prevent this, many 2FA implementations have tried to do away with multiple 2FA devices. Most of them (for purposes other than security) have settled on the least-common-denominator 2FA method - insecure SMS. Forgetting about the security aspects (very well covered elsewhere), I am also at the mercy of being in a network coverage area. This might not be the case when travelling to a location where your network provider does not have any roaming options.

Linux's oathtool is a nifty command line tool for websites that use standard HOTP/TOTP based 2FA (RFC6238). When enabling 2FA from the "Security Options", choose to authenticate using an "authenticator application". This should pop up with a QR code or it might offer you the option of copying the private key (pKey). Most of the time the pKey is encoded using base32. The tool uses SHA-1 by default, but this can be changed using the --totp=hash-algorithm option. However, you are at the mercy of the 2FA provider. Every time you need an OTP:

$ oathtool -b --totp "My Secret Key from some service provider"
191049

Suffice it to say, please keep the pKey private and encrypted using openssl or gpg. As it can be executed on any Linux device, this does not have to be your phone (which I keep losing or damaging). TOTP is especially cool for people who travel to different time zones as the OTP is derived based on Unix Time.

Configure Mutt to work with OAuth 2.0

My email client of choice is mutt. The keyboard short-cuts are ingrained into muscle memory. I have tried to use complex passwords to keep myself secure. While that may help, many large web service providers require the use of OAuth 2.0 for better security.

Mutt mail user agent (MUA)

The fine defenders of the galaxy at University of Glasgow IT started pushing for better security to access email and office365 applications. If Computer Scientists do not lead the way on these things, what hope is there for the rest of digital society?

Introduction

Peter van Ormondt wrote a simplified (for dummies) guide that even I could understand. It worked first time on Outlook365 and GMail. On GMail, I can now turn off "Less Secure Apps"1 that annoyingly keeps getting switched off, if the method is not utilised regularly.

A better understanding of how OAuth 2.0 has been implemented is explained in the OAuth 2.0 documentation found in the mutt repo. While Mutt has native OAuth2 support, it provides a hook to an external script to provide the authentication details. Conveniently, the Mutt project themselves have provided a Python script mutt_oauth2.py to authorise the user. The script keeps local state on a file which can be used to refresh the token. The mutt_oauth2.py script keeps this encrypted using gpg.

Configuration

Configure and Authorise with mutt_oauth2.py
  1. Create a separate gpg user to encrypt all the OAuth2 tokens for all providers. You could just as well re-use one of your other GPG keys for this.

    $ gpg --gen-key 
    GnuPG needs to construct a user ID to identify your key.
    
    Real name: My OAuth2 Token Encryption Key
    Email address: token.encryptor@oauth2.me
    You selected this USER-ID:
        "My OAuth2 Token Encryption Key <token.encryptor@oauth2.me>"
    
    Change (N)ame, (E)mail, or (O)kay/(Q)uit? O
    We need to generate a lot of random bytes. It is a good idea to perform
    some other action (type on the keyboard, move the mouse, utilize the
    disks) during the prime generation; this gives the random number
    generator a better chance to gain enough entropy.
    
  2. Download and install mutt_oauth2.py

    $ curl -o /any-path/mutt_oauth2.py https://gitlab.com/muttmua/mutt/-/raw/master/contrib/mutt_oauth2.py?inline=false
    $ chmod u+x /any-path/mutt_oauth2.py
    
  3. Replace YOUR_GPG_IDENTITY with your GPG key in mutt_oauth2.py

  4. Our setup masquerades as the Mozilla Thunderbird e-mail client and utilizes their client-id and client-secret which is hard-coded into the client. The client secret is actually within the open-source repos of the Thunderbird client. You can also create your own credentials. See instructions for GMail. The Thunderbird client registration details as of today :

  5. Intial authorisation for this client should be executed as: /any-path/mutt_oauth2.py /any-path/oath2_token_file --authorize. There should be a separate file for each email provider. When requested to input authorisation flow or authentication method, localhostauthcode will store the file in the same path. This is a one time operation and will be valid as long as the oauth2_token_file is available. You can delete the file and do the authorisation again if you so desire. Executing this script will provide a URL to paste into a browser. After opening the link in the browser and finishing any requisite authorisation, the script will obtain a token, encrypt it with your GPG key and store it locally in the path you have chosen.

Configure .mutt config

Add the following entries to the .mutt config file for OAUTH2 authentication.

set imap_authenticators = "oauthbearer:xoauth2"
set imap_oauth_refresh_command = "/any-path/mutt_oauth2.py /any-path/oath2_token_file"
set smtp_authenticators = ${imap_authenticators}
set smtp_oauth_refresh_command = ${imap_oauth_refresh_command}

xoauth2 was the experimental authentication protocol which got standardised as oauthbearer. However, it seems that while GMail seems to work with oauthbearer, Microsoft still requires xoauth2.

Roll your own Client credentials for GMail
  1. Login to your google account, and navigate to your developer console to generate OAuth 2.0 credentials
  2. Navigate to the "Credentials" page and click on + Create Credentials to create an OAuth client ID.

This client-ID and client-secret can then be used in the mutt_oauth2.py script.


  1. I fear the long term consequences of cajoling users by using manipulative language such as this. It will cause a loss of credibility for experts in the long run. Regaining trust that is once lost crying "Wolf" will only happen after a period of difficult consequences for both expert and layperson.