diff options
author | Marvin Borner | 2018-08-17 00:25:22 +0200 |
---|---|---|
committer | Marvin Borner | 2018-08-17 00:25:22 +0200 |
commit | e19577b5ebd40c235f933ac54d61f1c6442cd71a (patch) | |
tree | 69cc1c6066d68dd5d711f7278b05b428f9b8e25a | |
parent | e398bc3007a7d02f432d2f368369e9bf05cd7d7b (diff) |
Added secure oauth login and token storing
-rw-r--r-- | app/build.gradle | 3 | ||||
-rw-r--r-- | app/src/main/AndroidManifest.xml | 3 | ||||
-rw-r--r-- | app/src/main/java/com/no_name/no_name/LoginActivity.kt | 52 | ||||
-rw-r--r-- | app/src/main/java/com/no_name/no_name/MainActivity.kt | 4 | ||||
-rw-r--r-- | app/src/main/java/com/no_name/no_name/SecureStorage.kt | 61 | ||||
-rw-r--r-- | build.gradle | 1 |
6 files changed, 94 insertions, 30 deletions
diff --git a/app/build.gradle b/app/build.gradle index 0a33824..363ef6f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -23,6 +23,9 @@ android { } dependencies { + implementation 'com.github.mukeshsolanki:easypreferences:1.0.6' + implementation 'com.kazakago.cryptore:cryptore:1.3.0' + implementation 'com.github.kittinunf.fuel:fuel-android:1.6.0' implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation 'com.android.support:appcompat-v7:28.0.0-alpha1' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a0d6f61..31cb83c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,13 +1,16 @@ <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" package="com.no_name.no_name"> <!-- To auto-complete the email text field in the login form with the user's emails --> <uses-permission android:name="android.permission.GET_ACCOUNTS" /> <uses-permission android:name="android.permission.READ_PROFILE" /> <uses-permission android:name="android.permission.READ_CONTACTS" /> + <uses-permission android:name="android.permission.INTERNET" /> <application + tools:replace="android:allowBackup" android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" diff --git a/app/src/main/java/com/no_name/no_name/LoginActivity.kt b/app/src/main/java/com/no_name/no_name/LoginActivity.kt index 8cb61a3..154eb63 100644 --- a/app/src/main/java/com/no_name/no_name/LoginActivity.kt +++ b/app/src/main/java/com/no_name/no_name/LoginActivity.kt @@ -24,9 +24,10 @@ import android.view.inputmethod.EditorInfo import android.widget.ArrayAdapter import android.widget.TextView import android.widget.Toast -import com.no_name.no_name.MainActivity -import com.no_name.no_name.R +import com.github.kittinunf.fuel.android.extension.responseJson +import com.github.kittinunf.fuel.httpPost import kotlinx.android.synthetic.main.activity_login.* +import org.json.JSONObject import java.util.* /** @@ -243,23 +244,24 @@ class LoginActivity : AppCompatActivity(), LoaderCallbacks<Cursor> { inner class UserLoginTask internal constructor(private val mEmail: String, private val mPassword: String) : AsyncTask<Void, Void, Boolean>() { override fun doInBackground(vararg params: Void): Boolean? { - // TODO: attempt authentication against a network service. - - try { - // Simulate network access. - Thread.sleep(1000) - } catch (e: InterruptedException) { + val credentialJson = JSONObject() + credentialJson.put("email", mEmail) + credentialJson.put("password", mPassword) + + val (request, response, result) = "/login".httpPost() + .header("Content-Type" to "application/json") + .body(credentialJson.toString()) + .responseJson() + + result.fold(success = { + val secureStorage = SecureStorage(this@LoginActivity) + val accessToken = result.get().obj().getString("access_token") + secureStorage.set("access_token", accessToken) + val verifyToken = secureStorage.get("access_token") + return verifyToken == accessToken + }, failure = { return false - } - - return DUMMY_CREDENTIALS - .map { it.split(":") } - .firstOrNull { it[0] == mEmail } - ?.let { - // Account exists, return true if the password matches. - it[1] == mPassword - } - ?: true + }) } override fun onPostExecute(success: Boolean?) { @@ -267,13 +269,13 @@ class LoginActivity : AppCompatActivity(), LoaderCallbacks<Cursor> { showProgress(false) if (success!!) { - val toast = Toast.makeText(this@LoginActivity, "Successfully logged in.", Toast.LENGTH_LONG) - toast.setGravity(Gravity.CENTER, 0, 0) - toast.show() - val intent = Intent(this@LoginActivity, MainActivity::class.java) //intent.putExtra("keyIdentifier", value) startActivity(intent) + + val toast = Toast.makeText(this@LoginActivity, "Successfully logged in.", Toast.LENGTH_LONG) + toast.setGravity(Gravity.CENTER, 0, 0) + toast.show() } else { password.error = getString(R.string.error_incorrect_password) password.requestFocus() @@ -292,11 +294,5 @@ class LoginActivity : AppCompatActivity(), LoaderCallbacks<Cursor> { * Id to identity READ_CONTACTS permission request. */ private val REQUEST_READ_CONTACTS = 0 - - /** - * A dummy authentication store containing known user names and passwords. - * TODO: remove after connecting to a real authentication system. - */ - private val DUMMY_CREDENTIALS = arrayOf("foo@example.com:password") } } diff --git a/app/src/main/java/com/no_name/no_name/MainActivity.kt b/app/src/main/java/com/no_name/no_name/MainActivity.kt index 371ea97..10ae784 100644 --- a/app/src/main/java/com/no_name/no_name/MainActivity.kt +++ b/app/src/main/java/com/no_name/no_name/MainActivity.kt @@ -2,11 +2,10 @@ package com.no_name.no_name import android.content.Intent import android.os.Bundle -import android.support.design.widget.Snackbar import android.support.v7.app.AppCompatActivity import android.view.Menu import android.view.MenuItem - +import com.github.kittinunf.fuel.core.FuelManager import kotlinx.android.synthetic.main.activity_main.* class MainActivity : AppCompatActivity() { @@ -15,6 +14,7 @@ class MainActivity : AppCompatActivity() { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) setSupportActionBar(toolbar) + FuelManager.instance.basePath = "http://192.168.0.59" fab.setOnClickListener { view -> //Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG) diff --git a/app/src/main/java/com/no_name/no_name/SecureStorage.kt b/app/src/main/java/com/no_name/no_name/SecureStorage.kt new file mode 100644 index 0000000..5072f0d --- /dev/null +++ b/app/src/main/java/com/no_name/no_name/SecureStorage.kt @@ -0,0 +1,61 @@ +package com.no_name.no_name + +import android.content.Context +import android.preference.PreferenceManager +import android.util.Base64 +import com.kazakago.cryptore.CipherAlgorithm +import com.kazakago.cryptore.Cryptore +import com.madapps.prefrences.EasyPrefrences + + +class SecureStorage(private val context: Context) { + public fun set(key: String, value: String) { + sharedPrefs.putString(key, encryptAES(value)) + } + + public fun get(key: String): String { + return decryptAES(sharedPrefs.getString(key)) + } + + private val sharedPrefs = EasyPrefrences(context) + + private enum class Alias(val value: String) { + RSA("CIPHER_RSA"), + AES("CIPHER_AES") + } + + private val cryptoreAES: Cryptore by lazy { + val builder = Cryptore.Builder(alias = Alias.AES.value, type = CipherAlgorithm.AES) + // builder.blockMode = BlockMode.CBC //If Needed. + // builder.encryptionPadding = EncryptionPadding.PKCS7 //If Needed. + builder.build() + } + + private fun encryptAES(plainStr: String): String { + val plainByte = plainStr.toByteArray() + val result = cryptoreAES.encrypt(plainByte = plainByte) + cipherIV = result.cipherIV + return Base64.encodeToString(result.bytes, Base64.DEFAULT) + } + + private fun decryptAES(encryptedStr: String): String { + val encryptedByte = Base64.decode(encryptedStr, Base64.DEFAULT) + val result = cryptoreAES.decrypt(encryptedByte = encryptedByte, cipherIV = cipherIV) + return String(result.bytes) + } + + private var cipherIV: ByteArray? + get() { + val preferences = PreferenceManager.getDefaultSharedPreferences(this.context) + preferences.getString("cipher_iv", null)?.let { + return Base64.decode(it, Base64.DEFAULT) + } + return null + } + set(value) { + val preferences = PreferenceManager.getDefaultSharedPreferences(this.context) + val editor = preferences.edit() + editor.putString("cipher_iv", Base64.encodeToString(value, Base64.DEFAULT)) + editor.apply() + } +}
\ No newline at end of file diff --git a/build.gradle b/build.gradle index adf4e04..22ce23a 100644 --- a/build.gradle +++ b/build.gradle @@ -19,6 +19,7 @@ allprojects { repositories { google() jcenter() + maven { url "https://jitpack.io" } } } |