JWT AuthLoginManager Example
Here is a JWT auth manager example with simple login dialog.
You can replace login dialog with custom login fragment, a custom Login fragment example can be seen here CustomLoginFragment.
public class JwtAuthManagerJava implements AuthLoginManager {
private static final String NETWORK_NAME = "YOUR_NETWORK_NAME";
private String currentEmail = null;
@Override
public Observable<Credential> login(final Context context) {
final ObservableCallback<Credential> observableCallback = new ObservableCallback<Credential>();
final EditText emailField = new EditText(context);
emailField.setHint("Email");
LinearLayout layout = new LinearLayout(context);
layout.setOrientation(LinearLayout.VERTICAL);
layout.addView(emailField);
final CustomDialog.Builder dialog = new CustomDialog.Builder(context);
dialog.setTitle("Login to VouchrSDK")
.setView(layout)
.setPositiveButton("Login", new View.OnClickListener() {
@Override
public void onClick(View v) {
if (emailField.getText().toString().isEmpty()) {
Toast.makeText(context, "Need to enter info", Toast.LENGTH_LONG).show();
} else {
currentEmail = emailField.getText().toString();
Credential credential = new Credential(NETWORK_NAME, getJWT(currentEmail));
observableCallback.onSuccess(credential);
dialog.dismiss();
}
}
})
.setNegativeButton("Cancel", new View.OnClickListener() {
@Override
public void onClick(View v) {
observableCallback.onError(new Exception("Canceled"));
dialog.dismiss();
}
})
.show(ActivityUtil.getAppCompatActivity(context).getSupportFragmentManager());
return observableCallback.asObservable();
}
@Override
public Observable<SimpleUser> register(Context context, @Nullable String email) {
return Observable.just(SimpleUser.Builder.init("first", "last", currentEmail).create());
}
@Override
public Credential refreshToken(Context context) {
if (currentEmail == null) {
VouchrSDK.userManager().logout();
return null;
} else {
return new Credential(NETWORK_NAME, getJWT(currentEmail));
}
}
@Override
public void logout(Context context) {
}
@Override
public LoginInfo getNetworkInfo() {
return new LoginInfo(NETWORK_NAME, false, "Voucher SDK JWT Login");
}
// CRITICAL: for production uses, jwt must be created/signed by partner login service, not created locally and should be encrypted
// If you are using this local JWT for testing, select your application, then go to Dashboard / Developer / Authentication and set the authentication's Signature Type to NONE
private String getJWT(String username) {
JSONObject header = new JSONObject();
try {
header.put("alg", "none");
header.put("type", "jwt");
JSONObject claims = new JSONObject();
claims.put("sub", username);
StringBuilder sb = new StringBuilder();
sb.append(new String((toBase64(header.toString(), Base64.URL_SAFE)), Charset.defaultCharset()));
sb.append(".");
sb.append(new String((toBase64(claims.toString(), Base64.URL_SAFE)), Charset.defaultCharset()));
return sb.toString();
} catch (JSONException e) {
e.printStackTrace();
return null;
}
}
private byte[] toBase64(String string, int flags) {
byte[] bytes = string.getBytes(Charset.defaultCharset());
return Base64.encode(bytes, flags);
}
}
class JwtAuthManager : AuthLoginManager {
private val networkName = "YOUR_NETWORK_NAME"
private var currentEmail: String? = null
override fun login(context: Context): Observable<Credential> {
val observableCallback = ObservableCallback<Credential>()
var emailField: EditText =
EditText(context).apply {
hint = "email"
}
val layout = LinearLayout(context).apply {
orientation = VERTICAL
addView(emailField)
}
val dialog = CustomDialog.Builder(context)
dialog.setTitle("Login to VouchrSDK")
.setView(layout)
.setPositiveButton("Login", View.OnClickListener {
if (emailField.text.isNullOrEmpty()) {
Toast.makeText(context, "Need to enter info", Toast.LENGTH_LONG).show()
} else {
currentEmail = emailField.text.toString()
val credential = Credential(networkName, getJWT(currentEmail!!))
observableCallback.onSuccess(credential)
dialog.dismiss()
}
})
.setNegativeButton("Cancel", View.OnClickListener {
observableCallback.onError(Exception("Canceled"))
dialog.dismiss()
})
.show(ActivityUtil.getAppCompatActivity(context).supportFragmentManager)
return observableCallback.asObservable()
}
override fun register(context: Context, email: String?): Observable<SimpleUser>? {
return Observable.just(SimpleUser.Builder.init("first", "last", currentEmail).create());
}
override fun refreshToken(context: Context): Credential? {
if (currentEmail == null) {
Engine.userManager().logout()
return null
} else {
return Credential(networkName, getJWT(currentEmail!!))
}
}
override fun logout(context: Context) { }
override fun getNetworkInfo(): LoginInfo? {
return LoginInfo(networkName, false, "VoucherSDK JWTLogin")
}
// CRITICAL: for production uses, jwt must be created/signed by partner login service, not created locally and should be encrypted
// If you are using this local JWT for testing, select your application, then go to Dashboard / Developer / Authentication and set the authentication's Signature Type to NONE
private fun getJWT(username: String): String {
val header = JSONObject()
header.put("alg", "none")
header.put("type", "jwt")
val claims = JSONObject()
claims.put("sub", username)
val sb = StringBuilder()
sb.append(header.toString().toBase64(Base64.URL_SAFE).toString(Charset.defaultCharset()))
sb.append(".")
sb.append(claims.toString().toBase64(Base64.URL_SAFE).toString(Charset.defaultCharset()))
return sb.toString()
}
private fun String.toBase64(flags: Int = Base64.DEFAULT): ByteArray {
val bytes = this.toByteArray(Charset.defaultCharset())
return Base64.encode(bytes, flags)
}
}