/*
* Copyright (c) 2014-2017 Enrico M. Crisostomo
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of the author nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.warrenstrange.googleauth;
import org.apache.http.client.utils.URIBuilder;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
/**
* This class provides helper methods to create a QR code containing the
* provided credential. The generated QR code can be fed to the Google
* Authenticator application so that it can configure itself with the data
* contained therein.
*/
public final class GoogleAuthenticatorQRGenerator
{
/**
* The format string to generate the Google Chart HTTP API call.
*/
private static final String TOTP_URI_FORMAT =
"https://api.qrserver.com/v1/create-qr-code/?data=%s&size=200x200&ecc=M&margin=0";
/**
* This method wraps the invocation of URLEncoder##encode
* method using the "UTF-8" encoding. This call also wraps the
* UnsupportedEncodingException
thrown by
* URLEncoder##encode
into a RuntimeException
.
* Such an exception should never be thrown.
*
* @param s The string to URL-encode.
* @return the URL-encoded string.
*/
private static String internalURLEncode(String s)
{
try
{
return URLEncoder.encode(s, "UTF-8");
}
catch (UnsupportedEncodingException e)
{
throw new IllegalArgumentException("UTF-8 encoding is not supported by URLEncoder.", e);
}
}
/**
* The label is used to identify which account a key is associated with.
* It contains an account name, which is a URI-encoded string, optionally
* prefixed by an issuer string identifying the provider or service managing
* that account. This issuer prefix can be used to prevent collisions
* between different accounts with different providers that might be
* identified using the same account name, e.g. the user's email address.
* The issuer prefix and account name should be separated by a literal or
* url-encoded colon, and optional spaces may precede the account name.
* Neither issuer nor account name may themselves contain a colon.
* Represented in ABNF according to RFC 5234:
*
* label = accountname / issuer (“:” / “%3A”) *”%20” accountname * * @see Google Authenticator - KeyUriFormat */ private static String formatLabel(String issuer, String accountName) { if (accountName == null || accountName.trim().length() == 0) { throw new IllegalArgumentException("Account name must not be empty."); } StringBuilder sb = new StringBuilder(); if (issuer != null) { if (issuer.contains(":")) { throw new IllegalArgumentException("Issuer cannot contain the \':\' character."); } sb.append(issuer); sb.append(":"); } sb.append(accountName); return sb.toString(); } /** * Returns the URL of a Google Chart API call to generate a QR barcode to * be loaded into the Google Authenticator application. The user scans this * bar code with the application on their smart phones or enters the * secret manually. *
* The current implementation supports the following features: *
* The current implementation supports the following features: *