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)
    }
}