Skip to content

Instantly share code, notes, and snippets.

@momvart
Created August 19, 2020 10:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save momvart/ebeb853a1755e5ab621c99b5f15eefa1 to your computer and use it in GitHub Desktop.
Save momvart/ebeb853a1755e5ab621c99b5f15eefa1 to your computer and use it in GitHub Desktop.
A helper class which can generate a URI for google authenticator.
import android.net.Uri
object GoogleAuthenticatorUtils {
enum class KeyType(val uriKey: String) {
TIME_BASED("totp"),
COUNTER_BASED("hotp")
}
//Based on https://github.com/google/google-authenticator/wiki/Key-Uri-Format
/**
* Generate URI with containing the secret keys information:
* @param type A type which is either time based (totp) or counter based (hotp)
* @param issuer The issuer parameter is a string value indicating the provider or service this account is associated with, URL-encoded according to [RFC 3986](http://tools.ietf.org/html/rfc3986).
* @param accountName e.g. the user's email address
* @param secret The secret parameter is an arbitrary key value encoded in Base32 according to [RFC 3548](http://tools.ietf.org/html/rfc3548). The padding specified in [RFC 3548 section 2.2](https://tools.ietf.org/html/rfc3548#section-2.2) is not required and should be omitted.
* @param digits The digits parameter may have the values 6 or 8 (unless an [IllegalArgumentException] will be thrown), and determines how long of a one-time passcode to display to the user. The default is 6.
* @param counterOrPeriod This is counter for counter based keys and period in time based ones. The counter parameter is required when provisioning a key for use with HOTP. It will set the initial counter value. The period parameter defines a period that a TOTP code will be valid for, in seconds. The default value is 30.
* @return A URI in the following format: `otpauth://TYPE/LABEL?PARAMETERS` For example: `otpauth://totp/Example:alice@google.com?secret=JBSWY3DPEHPK3PXP&issuer=Example`
*/
fun generateGoogleAuthenticatorKeyUri(
type: KeyType,
issuer: String,
accountName: String,
secret: String,
digits: Int? = null,
counterOrPeriod: Int? = null
): Uri = Uri.Builder()
.scheme("otpauth")
.authority(type.uriKey)
.appendPath("$issuer:$accountName")
.appendQueryParameter("secret", secret)
.appendQueryParameter("issuer", issuer)
.apply {
if (digits == null)
return@apply
if (digits != 6 && digits != 8)
throw IllegalArgumentException("Digits param must be 6 or 8. Current value: $digits")
appendQueryParameter("digits", digits.toString())
}
.apply {
when (type) {
KeyType.COUNTER_BASED -> {
if (counterOrPeriod == null)
throw IllegalArgumentException("Counter param is required when key type is counter based.")
appendQueryParameter("counter", counterOrPeriod.toString())
}
KeyType.TIME_BASED -> {
counterOrPeriod?.let { appendQueryParameter("period", it.toString()) }
}
}
}
.build()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment