Skip to content

Instantly share code, notes, and snippets.

@ewanharris
Last active August 19, 2020 10:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ewanharris/16909adfbfb43978858d5e7169d1bc9c to your computer and use it in GitHub Desktop.
Save ewanharris/16909adfbfb43978858d5e7169d1bc9c to your computer and use it in GitHub Desktop.
Webdialog testing
const wd = require('ti.webdialog');
const deeply = OS_ANDROID ? require('ti.deeply') : null;
const client_id = '<insert_client_id>';
const redirect_uri = 'testapp://login'
const state = generateGUID();
const win = Ti.UI.createWindow()
const lbl = Ti.UI.createLabel({ text: 'Click me' });
lbl.addEventListener('click', () => {
const url = buildURL('https://login.axway.com/auth/realms/Broker/protocol/openid-connect/auth', {
response_type: 'code',
client_id,
redirect_uri,
scope: 'openid',
state
});
const webdialogOptions = { url };
if (OS_ANDROID) {
webdialogOptions.intentFlags = Ti.Android.FLAG_ACTIVITY_NO_HISTORY | Ti.Android.FLAG_ACTIVITY_NEW_TASK
}
if (OS_ANDROID) {
deeply.setCallback(handleUrl);
} else if (OS_IOS) {
Ti.App.iOS.addEventListener('handleurl', handleUrl);
}
wd.addEventListener('close', handleClose);
wd.open(webdialogOptions);
});
win.add(lbl);
win.open();
function buildURL(baseURL, params) {
var encodedParams = [];
for (var param in params) {
if (params.hasOwnProperty(param)) {
encodedParams.push(encodeURIComponent(param) + '=' + encodeURIComponent(params[param]));
}
}
return baseURL + '?' + encodedParams.join('&');
}
function generateGUID() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
return v.toString(16);
});
}
function parseQueryParams(url, callbackUrl) {
var queryParams = {},
pairs = [],
keyValuePair;
// FIXME handle when there are no query params?
pairs = decodeURI(url).slice(callbackUrl.length + 1).split('&'); // cut off base callback URL and ? char
for (var i = 0; i < pairs.length; i++) {
keyValuePair = pairs[i].split('=');
queryParams[keyValuePair[0]] = keyValuePair[1];
}
return queryParams;
}
async function request({ body, url, headers = {}, method = 'GET', timeout = 5000, json = false, file }) {
return new Promise((resolve, reject) => {
var client = Ti.Network.createHTTPClient({
onload: function () {
if (json) {
return resolve(JSON.parse(this.responseText));
}
return resolve(this.responseText);
},
onerror: function () {
const response = {
status: this.status
};
if (json) {
try {
response.response = JSON.parse(this.responseText);
} catch (e) {
response.response = this.responseText;
}
} else {
response.response = JSON.parse(this.responseText);
}
return reject(response);
},
timeout
});
client.open(method, url);
for (const [ headerName, value ] of Object.entries(headers)) {
client.setRequestHeader(headerName, value);
}
if (body) {
client.send(body);
} else {
client.send();
}
});
};
async function handleUrl (eventData) {
wd.removeEventListener('close', handleClose);
let launchInformation;
// Extract the URL out of the event data
if (OS_ANDROID) {
launchInformation = eventData.data;
} else if (OS_IOS) {
launchInformation = eventData.launchOptions.url;
}
if (launchInformation && !launchInformation.startsWith(redirect_uri)) {
console.log(`Ignoring ${launchInformation}`);
return;
}
// Remove the handleUrl call
// TODO: can we remove this on Android? It doesn't look like ti.deeply supports unsetting the handler
if (OS_IOS) {
Ti.App.iOS.removeEventListener('handleurl', handleUrl);
wd.close();
}
// Parse out the data from the URL
const queryParams = parseQueryParams(launchInformation, redirect_uri);
if (queryParams.error) {
console.error(queryParams.error);
}
if (queryParams.code) {
// check CSRF
if (queryParams.state !== state) {
console.error(`Possible Cross-site request forgery. ${state} doesn\'t match ${queryParams.state}`);
return;
}
const token = await request({
body: {
grant_type: 'authorization_code',
code: queryParams.code,
redirect_uri,
client_id
},
url: 'https://login.axway.com/auth/realms/Broker/protocol/openid-connect/token',
method: 'POST',
json: true
});
// This just gets information about the user associated with the access token
const userInfo = await request({
url: 'https://login.axway.com/auth/realms/Broker/protocol/openid-connect/userinfo',
json: true,
headers: {
Accept: 'application/json',
Authorization: `Bearer ${token.access_token}`
},
});
alert(userInfo.name);
}
}
function handleClose(e) {
console.log(e);
}
<!-- snippets from the tiapp to get this working -->
<!-- Add CFBundleURLTypes to your ios plist section -->
<ios>
<plist>
<dict>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>testapp</string>
</array>
</dict>
</array>
</dict>
</plist>
</ios>
<!-- Add the deeplink handler to your Android Manifest section -->
<android xmlns:android="http://schemas.android.com/apk/res/android">
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1234">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.CAMERA" />
<application>
<activity android:name="ti.deeply.DeepLinkHandlerActivity" android:noHistory="true" android:excludeFromRecents="true" android:theme="@android:style/Theme.NoDisplay" android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="login"
android:scheme="testapp" />
</intent-filter>
</activity>
</application>
</manifest>
</android>
<!-- required modules -->
<modules>
<module>ti.identity</module>
<module>ti.webdialog</module>
<!-- https://github.com/caffeinalab/ti.deeply -->
<module platform="android">ti.deeply</module>
</modules>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment