Reputation: 59
I need to receive the token on my Android aplication. I created and API on Laravel, and i need to receive an authentication token, but i don't know how to do it on Android. I did some code but it doesn't work.
public class LoginActivity extends AppCompatActivity {
WebView webView;
private final String URL = "https://login.ipleiria.pt/adfs/ls/?client-request-id=5d88995c-4405-40c7-985f-a02fd6d62749&username=&wa=wsignin1.0&wtrealm=urn%3afederation%3aMicrosoftOnline&wctx=estsredirect%3d2%26estsrequest%3drQIIAY2RO2_TUABGc-PEbaMKKsTAgEQHpEpI176-14_YEhLOw2mihDRJCWCBKtuxEzdObPzIa2Pr2IEBOiHElJEBIf4AUsXQqUN_QcWEmBgYaMTCBmc4-ubz3aM4hlPuoj9guDJEjsNBy16tvwhv5LaevTl6ni19efD64C17fr5TPQHXRnPGDTzbDV2DCeIluDOI4yBSWNZPYs_3h4zvOK5lM5Y_Yv2pwX4C4AyAZVoSiZiX8rKABUw4TLBAGCKKHI-wDEWMLMjjngMNCROICTIkx-Z4yxQv0tebahIP8Ep-6C7sH-kNxw9HB4EfxSfUK1Cy4kIpqvbL5UIb1RO-3PcXjXqnPjuM-b6gNatoaFZQ7XBSRxGJZTnUO2Iv6DWTmdgtVrwGP2sN1HGguhW3PVet3eFcm-JW-2k3atSQqor7Lyb8UINDSCJnz8vbu16Xx9CR9Xwy6xgjTeppiVM3ySNB79RMW-C6e3BJ_VfjDxR91Wnkj08p2g_ssds7y4BvmU1EKevrua3UrdR26mcGvMteffH-csreXtspvZzYvz5ufk2dZlm2bZS1_mLgdcbF_ccto2BOpPzDqDEvPklCvWvpbWLwXpUvmf37ROGOaXBM05c0-E6Do7XU541_fXeRu4kRJ0NEIMdtc0hBSBGw_hs1&RedirectToIdentityProvider=http%3a%2f%2flogin.ipleiria.pt%2fadfs%2fservices%2ftrust";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login);
webView = findViewById(R.id.webView);
webView.setWebViewClient(new WebViewClient());
webView.loadUrl(URL);
// Cria problemas de XSS na aplicação. Usar com cuidado
webView.getSettings().setJavaScriptEnabled(true);
if (URL.length() == 0) {
getToken("https://login.ipleiria.pt/adfs/ls/?client-request-id=5d88995c-4405-40c7-985f-a02fd6d62749&username=&wa=wsignin1.0&wtrealm=urn%3afederation%3aMicrosoftOnline&wctx=estsredirect%3d2%26estsrequest%3drQIIAY2RO2_TUABGc-PEbaMKKsTAgEQHpEpI176-14_YEhLOw2mihDRJCWCBKtuxEzdObPzIa2Pr2IEBOiHElJEBIf4AUsXQqUN_QcWEmBgYaMTCBmc4-ubz3aM4hlPuoj9guDJEjsNBy16tvwhv5LaevTl6ni19efD64C17fr5TPQHXRnPGDTzbDV2DCeIluDOI4yBSWNZPYs_3h4zvOK5lM5Y_Yv2pwX4C4AyAZVoSiZiX8rKABUw4TLBAGCKKHI-wDEWMLMjjngMNCROICTIkx-Z4yxQv0tebahIP8Ep-6C7sH-kNxw9HB4EfxSfUK1Cy4kIpqvbL5UIb1RO-3PcXjXqnPjuM-b6gNatoaFZQ7XBSRxGJZTnUO2Iv6DWTmdgtVrwGP2sN1HGguhW3PVet3eFcm-JW-2k3atSQqor7Lyb8UINDSCJnz8vbu16Xx9CR9Xwy6xgjTeppiVM3ySNB79RMW-C6e3BJ_VfjDxR91Wnkj08p2g_ssds7y4BvmU1EKevrua3UrdR26mcGvMteffH-csreXtspvZzYvz5ufk2dZlm2bZS1_mLgdcbF_ccto2BOpPzDqDEvPklCvWvpbWLwXpUvmf37ROGOaXBM05c0-E6Do7XU541_fXeRu4kRJ0NEIMdtc0hBSBGw_hs1&RedirectToIdentityProvider=http%3a%2f%2flogin.ipleiria.pt%2fadfs%2fservices%2ftrust");
}
}
private void getToken(String url) {
StringBuilder strBuild = new StringBuilder();
String authURL = "https://login.ipleiria.pt/adfs/ls/?client-request-id=5d88995c-4405-40c7-985f-a02fd6d62749&username=&wa=wsignin1.0&wtrealm=urn%3afederation%3aMicrosoftOnline&wctx=estsredirect%3d2%26estsrequest%3drQIIAY2RO2_TUABGc-PEbaMKKsTAgEQHpEpI176-14_YEhLOw2mihDRJCWCBKtuxEzdObPzIa2Pr2IEBOiHElJEBIf4AUsXQqUN_QcWEmBgYaMTCBmc4-ubz3aM4hlPuoj9guDJEjsNBy16tvwhv5LaevTl6ni19efD64C17fr5TPQHXRnPGDTzbDV2DCeIluDOI4yBSWNZPYs_3h4zvOK5lM5Y_Yv2pwX4C4AyAZVoSiZiX8rKABUw4TLBAGCKKHI-wDEWMLMjjngMNCROICTIkx-Z4yxQv0tebahIP8Ep-6C7sH-kNxw9HB4EfxSfUK1Cy4kIpqvbL5UIb1RO-3PcXjXqnPjuM-b6gNatoaFZQ7XBSRxGJZTnUO2Iv6DWTmdgtVrwGP2sN1HGguhW3PVet3eFcm-JW-2k3atSQqor7Lyb8UINDSCJnz8vbu16Xx9CR9Xwy6xgjTeppiVM3ySNB79RMW-C6e3BJ_VfjDxR91Wnkj08p2g_ssds7y4BvmU1EKevrua3UrdR26mcGvMteffH-csreXtspvZzYvz5ufk2dZlm2bZS1_mLgdcbF_ccto2BOpPzDqDEvPklCvWvpbWLwXpUvmf37ROGOaXBM05c0-E6Do7XU541_fXeRu4kRJ0NEIMdtc0hBSBGw_hs1&RedirectToIdentityProvider=http%3a%2f%2flogin.ipleiria.pt%2fadfs%2fservices%2ftrust";
String redirect_uri = "urn:ietf:wg:oauth:2.0:oob";
strBuild.append("&redirect_uri=").append(redirect_uri);
try{
java.net.URL obj = new URL(authURL);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setDoOutput(true);
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.writeBytes(strBuild.toString());
wr.flush();
wr.close();
System.out.println(con.getResponseCode());
System.out.println(con.getResponseMessage());
}catch (Exception e)
{
System.out.println("Error.");
}
System.out.println(strBuild.toString());
}
}
Upvotes: 5
Views: 15331
Reputation: 193
The first one was quite good for me with some modification
class JavaScriptInterface(private val token: String, private val webView: WebView) {
@JavascriptInterface
fun addAuthorizationHeader() {
webView.evaluateJavascript("XMLHttpRequest.setRequestHeader('Authorization', 'Bearer ' + $token)", null)
}
}
I also had to set javaScriptEnabled to true and I also add SuppressLint:
@SuppressLint("SetJavascriptEnabled")
private fun setWebViewEventsOnline(): WebView {
webView.settings.javaScriptEnabled = true
val javaScriptInterface = JavaScriptInterface(Dao().getToken(), webView)
//...
}
I also had to overwrite some WebViewClient function:
webView.webViewClient = object : WebViewClient() {
override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
if (url.startsWith(Constants.BASE_URL)) {
val authorizationHeader = mapOf("Authorization" to "Bearer ${Dao().getToken()}")
view.loadUrl(url, authorizationHeader)
return true
}
return super.shouldOverrideUrlLoading(view, url)
}
override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
super.onPageStarted(view, url, favicon)
javaScriptInterface.addAuthorizationHeader()
}
}
I also had to add the authorization header when I loadUrl:
val authorizationHeader = mapOf("Authorization" to "Bearer ${Dao().getCookie()}")
webView.loadUrl(url, authorizationHeader)
Upvotes: 1
Reputation: 4206
Ok you have two options:
First one
The first one is the better one. You can do this if you have access to the code of the Web frontend. Basically you just add a WebAppInterface
. The documentation describes it really well. Your android function should accept the token as a parameter and it should be called by your frontend after the user successfully logged in and has gotten his token.
So yours could look like this:
class WebAppInterface(private val mContext: Context) {
/** Show a toast from the web page */
@JavascriptInterface
fun consumeToken(token: String) {
//do whatever you want to do with the token.
}
}
You must register it like this: webView.addJavascriptInterface(WebAppInterface(this), "Android")
Then your Web frontend (the javascript side) can invoke the function like that: Android.consumeToken(token);
Second one
This one is a bit more complicated. Load your url like usual and set a WebViewClient to your WebView
. Like this:
webView.webViewClient = object: WebViewClient() {
override fun onPageFinished(view: WebView?, url: String?) {
super.onPageFinished(view, url)
webView.evaluateJavascript("(function() { return JSON.stringify(localStorage); })();") { s ->
if (s != "\"{}\"") {
var jsonAsStr = s.substring(1, s.length - 1).replace("\\", "")
val obj = JSONObject(jsonAsStr)
val token = obj.getString("token")
}
}
}
}
webView.loadUrl("https://www.google.com/")
So onPageFinished
is called when a new site loads. This way you know that the user completed the login (yes if there where any other buttons or so that he could click those would trigger this function as well). However you could catch those errors by checking the url in the onPageStarted
and see if this matches the page the user should see after login. So like this: onPageStarted
gets called -> if the url matches the url of the page the user should see after the login then its the correct one and you can invoke the evaluateJavascript
. But maybe my simple example is enough for your usecase.
Anyway the evaluateJavascript
then injects javascript in the client which will read the localStorage
. This is then checked if it's empty or not and afterwards parsed to a jsonObject
. Then just retrieve the token from the jsonified localstorage. Thats it :)
Same thing in Java:
webView.setWebViewClient(new WebViewClient() {
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
webView.evaluateJavascript("(function() { return JSON.stringify(localStorage); })();", new ValueCallback<String>() {
@Override
public void onReceiveValue(String s) {
if (s != "\"{}\"") {
String jsonAsStr = s.substring(1, s.length() - 1).replace("\\", "");
try {
JSONObject obj = new JSONObject(jsonAsStr);
String token = obj.getString("token");
} catch (JSONException e) {
}
}
}
});
}
});
Upvotes: 3