KEYCLOAK-2606: add support for native browsers on cordova
KEYCLOAK-2606 Added cordova native KEYCLOAK-2606 Some more fixes and tweaks Fix redirect in example realm feature(cordova-native): fix universalLinks and kc options Added 'cordova-native' to typings Added an option to define a "default" redirectUri in keycloak.js Added 'login' and 'logout' event to universalLinks configuration in config.xml Improved 'cordova-native' example to always use a redirectUri and update state after successfull logout Setting the 'authenticated' flag for the keycloak instance to 'false' after a logout redirect KEYCLOAK-2606: Simplify example for cordova-native I wanted to make it explicit which options are actually needed, so I didn't want to reuse the keycloak conf KEYCLOAK-2606: simplify example The update state after logout shouldn't be necessary as it is set in `keycloak.onAuthLogout = updateState;` Not sure why it is called after the login promise... Fixes
This commit is contained in:
parent
8e20986335
commit
3417b569c0
9 changed files with 741 additions and 5 deletions
|
@ -29,7 +29,7 @@ export = Keycloak;
|
||||||
declare function Keycloak(config?: string|{}): Keycloak.KeycloakInstance;
|
declare function Keycloak(config?: string|{}): Keycloak.KeycloakInstance;
|
||||||
|
|
||||||
declare namespace Keycloak {
|
declare namespace Keycloak {
|
||||||
type KeycloakAdapterName = 'cordova'|'default' | any;
|
type KeycloakAdapterName = 'cordova' | 'cordova-native' |'default' | any;
|
||||||
type KeycloakOnLoad = 'login-required'|'check-sso';
|
type KeycloakOnLoad = 'login-required'|'check-sso';
|
||||||
type KeycloakResponseMode = 'query'|'fragment';
|
type KeycloakResponseMode = 'query'|'fragment';
|
||||||
type KeycloakResponseType = 'code'|'id_token token'|'code id_token token';
|
type KeycloakResponseType = 'code'|'id_token token'|'code id_token token';
|
||||||
|
@ -98,6 +98,12 @@ declare namespace Keycloak {
|
||||||
*/
|
*/
|
||||||
responseMode?: KeycloakResponseMode;
|
responseMode?: KeycloakResponseMode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies a default uri to redirect to after login or logout.
|
||||||
|
* This is currently supported for adapter 'cordova-native' and 'default'
|
||||||
|
*/
|
||||||
|
redirectUri?: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the OpenID Connect flow.
|
* Set the OpenID Connect flow.
|
||||||
* @default standard
|
* @default standard
|
||||||
|
|
|
@ -46,11 +46,10 @@
|
||||||
kc.authenticated = false;
|
kc.authenticated = false;
|
||||||
|
|
||||||
callbackStorage = createCallbackStorage();
|
callbackStorage = createCallbackStorage();
|
||||||
|
var adapters = ['default', 'cordova', 'cordova-native'];
|
||||||
|
|
||||||
if (initOptions && initOptions.adapter === 'cordova') {
|
if (initOptions && adapters.indexOf(initOptions.adapter) > -1) {
|
||||||
adapter = loadAdapter('cordova');
|
adapter = loadAdapter(initOptions.adapter);
|
||||||
} else if (initOptions && initOptions.adapter === 'default') {
|
|
||||||
adapter = loadAdapter();
|
|
||||||
} else if (initOptions && typeof initOptions.adapter === "object") {
|
} else if (initOptions && typeof initOptions.adapter === "object") {
|
||||||
adapter = initOptions.adapter;
|
adapter = initOptions.adapter;
|
||||||
} else {
|
} else {
|
||||||
|
@ -106,6 +105,10 @@
|
||||||
if (initOptions.timeSkew != null) {
|
if (initOptions.timeSkew != null) {
|
||||||
kc.timeSkew = initOptions.timeSkew;
|
kc.timeSkew = initOptions.timeSkew;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(initOptions.redirectUri) {
|
||||||
|
kc.redirectUri = initOptions.redirectUri;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!kc.responseMode) {
|
if (!kc.responseMode) {
|
||||||
|
@ -1339,6 +1342,75 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (type == 'cordova-native') {
|
||||||
|
loginIframe.enable = false;
|
||||||
|
|
||||||
|
return {
|
||||||
|
login: function(options) {
|
||||||
|
var promise = createPromise();
|
||||||
|
var loginUrl = kc.createLoginUrl(options);
|
||||||
|
|
||||||
|
universalLinks.subscribe('keycloak', function(event) {
|
||||||
|
universalLinks.unsubscribe('keycloak');
|
||||||
|
window.cordova.plugins.browsertab.close();
|
||||||
|
var oauth = parseCallback(event.url);
|
||||||
|
processCallback(oauth, promise);
|
||||||
|
});
|
||||||
|
|
||||||
|
window.cordova.plugins.browsertab.openUrl(loginUrl);
|
||||||
|
return promise.promise;
|
||||||
|
},
|
||||||
|
|
||||||
|
logout: function(options) {
|
||||||
|
var promise = createPromise();
|
||||||
|
var logoutUrl = kc.createLogoutUrl(options);
|
||||||
|
|
||||||
|
universalLinks.subscribe('keycloak', function(event) {
|
||||||
|
universalLinks.unsubscribe('keycloak');
|
||||||
|
window.cordova.plugins.browsertab.close();
|
||||||
|
kc.clearToken();
|
||||||
|
promise.setSuccess();
|
||||||
|
});
|
||||||
|
|
||||||
|
window.cordova.plugins.browsertab.openUrl(logoutUrl);
|
||||||
|
return promise.promise;
|
||||||
|
},
|
||||||
|
|
||||||
|
register : function(options) {
|
||||||
|
var promise = createPromise();
|
||||||
|
var registerUrl = kc.createRegisterUrl(options);
|
||||||
|
universalLinks.subscribe('keycloak' , function(event) {
|
||||||
|
universalLinks.unsubscribe('keycloak');
|
||||||
|
window.cordova.plugins.browsertab.close();
|
||||||
|
var oauth = parseCallback(event.url);
|
||||||
|
processCallback(oauth, promise);
|
||||||
|
});
|
||||||
|
window.cordova.plugins.browsertab.openUrl(registerUrl);
|
||||||
|
return promise.promise;
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
accountManagement : function() {
|
||||||
|
var accountUrl = kc.createAccountUrl();
|
||||||
|
if (typeof accountUrl !== 'undefined') {
|
||||||
|
window.cordova.plugins.browsertab.openUrl(accountUrl);
|
||||||
|
} else {
|
||||||
|
throw "Not supported by the OIDC server";
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
redirectUri: function(options) {
|
||||||
|
if (options && options.redirectUri) {
|
||||||
|
return options.redirectUri;
|
||||||
|
} else if (kc.redirectUri) {
|
||||||
|
return kc.redirectUri;
|
||||||
|
} else {
|
||||||
|
return "http://localhost";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
throw 'invalid adapter type: ' + type;
|
throw 'invalid adapter type: ' + type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
6
examples/cordova-native/.gitignore
vendored
Normal file
6
examples/cordova-native/.gitignore
vendored
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
platforms
|
||||||
|
plugins
|
||||||
|
www/keycloak.js
|
||||||
|
www/keycloak.json
|
||||||
|
node_modules
|
||||||
|
ul_web_hooks
|
36
examples/cordova-native/README.md
Normal file
36
examples/cordova-native/README.md
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
Basic Cordova Example
|
||||||
|
=====================
|
||||||
|
|
||||||
|
Before running this example you need to have Cordova installed with a phone or emulator available.
|
||||||
|
|
||||||
|
Start and configure Keycloak
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
Start Keycloak bound to an IP address available to the phone or emulator. For example:
|
||||||
|
|
||||||
|
bin/standalone.sh -b 192.168.0.10
|
||||||
|
|
||||||
|
Open the Keycloak admin console, click on Add Realm, click on 'Choose a JSON file', selct example-realm.json and click Upload.
|
||||||
|
|
||||||
|
Navigate to applications, click on 'Cordova', select 'Installation' and in the 'Format option' drop-down select 'keycloak.json'. Download this file to the www folder.
|
||||||
|
|
||||||
|
Download '/js/keycloak.js' from the server to the www folder as well. For example:
|
||||||
|
|
||||||
|
wget http://192.168.0.10:8080/auth/js/keycloak.js
|
||||||
|
|
||||||
|
|
||||||
|
Install to Android phone or emulator
|
||||||
|
------------------------------------
|
||||||
|
|
||||||
|
cordova platform add android
|
||||||
|
cordova run android
|
||||||
|
|
||||||
|
|
||||||
|
Once the application is opened you can login with username: 'user', and password: 'password'.
|
||||||
|
|
||||||
|
|
||||||
|
Troubleshooting
|
||||||
|
-----------------------------------------
|
||||||
|
|
||||||
|
* You always need to initialize keycloak after the 'deviceready' event. Otherwise Cordova mode won't be enabled for keycloak.js.
|
||||||
|
* 'http://localhost' should be listed in the allowed redirects in client configuration, but never 'file:///android_asset'.
|
25
examples/cordova-native/config.xml
Normal file
25
examples/cordova-native/config.xml
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<widget id="org.keycloak.examples.cordova" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:gap="http://phonegap.com/ns/1.0">
|
||||||
|
<name>Keycloak Auth</name>
|
||||||
|
<description>Keycloak Cordova Example</description>
|
||||||
|
<author href="http://www.keycloak.org">Keycloak Team</author>
|
||||||
|
<feature name="http://api.phonegap.com/1.0/device" />
|
||||||
|
<preference name="permissions" value="none" />
|
||||||
|
<preference name="AndroidLaunchMode" value="singleInstance" />
|
||||||
|
<gap:plugin name="cordova-plugin-inappbrowser" />
|
||||||
|
<gap:plugin name="cordova-plugin-whitelist" source="npm" version="1.0.0" />
|
||||||
|
<access origin="*" />
|
||||||
|
<allow-navigation href="*" />
|
||||||
|
<allow-intent href="http://*/*" />
|
||||||
|
<allow-intent href="https://*/*" />
|
||||||
|
<preference name="AndroidLaunchMode" value="singleTask" />
|
||||||
|
<universal-links>
|
||||||
|
<host name="keycloak-cordova-example.github.io" scheme="https">
|
||||||
|
<path event="keycloak" url="/login" />
|
||||||
|
</host>
|
||||||
|
</universal-links>
|
||||||
|
<plugin name="cordova-plugin-browsertab" spec="~0.2.0" />
|
||||||
|
<plugin name="cordova-plugin-deeplinks" spec="^1.1.0" />
|
||||||
|
<engine name="ios" spec="^4.5.4" />
|
||||||
|
<engine name="android" spec="^6.4.0" />
|
||||||
|
</widget>
|
61
examples/cordova-native/example-realm.json
Executable file
61
examples/cordova-native/example-realm.json
Executable file
|
@ -0,0 +1,61 @@
|
||||||
|
{
|
||||||
|
"realm": "example",
|
||||||
|
"enabled": true,
|
||||||
|
"sslRequired": "external",
|
||||||
|
"registrationAllowed": true,
|
||||||
|
"privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
|
||||||
|
"publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
|
||||||
|
"requiredCredentials": [ "password" ],
|
||||||
|
"users" : [
|
||||||
|
{
|
||||||
|
"username" : "user",
|
||||||
|
"enabled": true,
|
||||||
|
"email" : "sample-user@example",
|
||||||
|
"firstName": "Sample",
|
||||||
|
"lastName": "User",
|
||||||
|
"credentials" : [
|
||||||
|
{ "type" : "password",
|
||||||
|
"value" : "password" }
|
||||||
|
],
|
||||||
|
"realmRoles": [ "user" ],
|
||||||
|
"clientRoles": {
|
||||||
|
"account": ["view-profile", "manage-account"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"roles" : {
|
||||||
|
"realm" : [
|
||||||
|
{
|
||||||
|
"name": "user",
|
||||||
|
"description": "User privileges"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "admin",
|
||||||
|
"description": "Administrator privileges"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"scopeMappings": [
|
||||||
|
{
|
||||||
|
"client": "cordova",
|
||||||
|
"roles": ["user"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"clients": [
|
||||||
|
{
|
||||||
|
"clientId": "cordova",
|
||||||
|
"enabled": true,
|
||||||
|
"publicClient": true,
|
||||||
|
"redirectUris": ["android-app://org.keycloak.examples.cordova/https/keycloak-cordova-example.github.io/login"],
|
||||||
|
"webOrigins": ["localhost"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"clientScopeMappings": {
|
||||||
|
"account": [
|
||||||
|
{
|
||||||
|
"client": "cordova",
|
||||||
|
"roles": ["view-profile"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
383
examples/cordova-native/package-lock.json
generated
Normal file
383
examples/cordova-native/package-lock.json
generated
Normal file
|
@ -0,0 +1,383 @@
|
||||||
|
{
|
||||||
|
"name": "org.keycloak.examples.cordova",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"lockfileVersion": 1,
|
||||||
|
"requires": true,
|
||||||
|
"dependencies": {
|
||||||
|
"balanced-match": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
|
||||||
|
},
|
||||||
|
"base64-js": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-ccav/yGvoa80BQDljCxsmmQ3Xvx60/UpBIij5QN21W3wBi/hhIC9OoO+KLpu9IJTS9j4DRVJ3aDDF9cMSoa2lw=="
|
||||||
|
},
|
||||||
|
"brace-expansion": {
|
||||||
|
"version": "1.1.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||||
|
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||||
|
"requires": {
|
||||||
|
"balanced-match": "1.0.0",
|
||||||
|
"concat-map": "0.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"concat-map": {
|
||||||
|
"version": "0.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||||
|
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
|
||||||
|
},
|
||||||
|
"cordova-android": {
|
||||||
|
"version": "6.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/cordova-android/-/cordova-android-6.4.0.tgz",
|
||||||
|
"integrity": "sha1-VK6NpXKKjX5e/MYXLT3MoXvH/n0=",
|
||||||
|
"requires": {
|
||||||
|
"android-versions": "1.2.1",
|
||||||
|
"cordova-common": "2.1.0",
|
||||||
|
"elementtree": "0.1.6",
|
||||||
|
"nopt": "3.0.6",
|
||||||
|
"properties-parser": "0.2.3",
|
||||||
|
"q": "1.5.0",
|
||||||
|
"shelljs": "0.5.3"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"abbrev": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"bundled": true
|
||||||
|
},
|
||||||
|
"android-versions": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"bundled": true
|
||||||
|
},
|
||||||
|
"ansi": {
|
||||||
|
"version": "0.3.1",
|
||||||
|
"bundled": true
|
||||||
|
},
|
||||||
|
"balanced-match": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"bundled": true
|
||||||
|
},
|
||||||
|
"base64-js": {
|
||||||
|
"version": "0.0.8",
|
||||||
|
"bundled": true
|
||||||
|
},
|
||||||
|
"big-integer": {
|
||||||
|
"version": "1.6.25",
|
||||||
|
"bundled": true
|
||||||
|
},
|
||||||
|
"bplist-parser": {
|
||||||
|
"version": "0.1.1",
|
||||||
|
"bundled": true,
|
||||||
|
"requires": {
|
||||||
|
"big-integer": "1.6.25"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"brace-expansion": {
|
||||||
|
"version": "1.1.8",
|
||||||
|
"bundled": true,
|
||||||
|
"requires": {
|
||||||
|
"balanced-match": "1.0.0",
|
||||||
|
"concat-map": "0.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"concat-map": {
|
||||||
|
"version": "0.0.1",
|
||||||
|
"bundled": true
|
||||||
|
},
|
||||||
|
"cordova-common": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"bundled": true,
|
||||||
|
"requires": {
|
||||||
|
"ansi": "0.3.1",
|
||||||
|
"bplist-parser": "0.1.1",
|
||||||
|
"cordova-registry-mapper": "1.1.15",
|
||||||
|
"elementtree": "0.1.6",
|
||||||
|
"glob": "5.0.15",
|
||||||
|
"minimatch": "3.0.4",
|
||||||
|
"osenv": "0.1.4",
|
||||||
|
"plist": "1.2.0",
|
||||||
|
"q": "1.5.0",
|
||||||
|
"semver": "5.4.1",
|
||||||
|
"shelljs": "0.5.3",
|
||||||
|
"underscore": "1.8.3",
|
||||||
|
"unorm": "1.4.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"cordova-registry-mapper": {
|
||||||
|
"version": "1.1.15",
|
||||||
|
"bundled": true
|
||||||
|
},
|
||||||
|
"elementtree": {
|
||||||
|
"version": "0.1.6",
|
||||||
|
"bundled": true,
|
||||||
|
"requires": {
|
||||||
|
"sax": "0.3.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"glob": {
|
||||||
|
"version": "5.0.15",
|
||||||
|
"bundled": true,
|
||||||
|
"requires": {
|
||||||
|
"inflight": "1.0.6",
|
||||||
|
"inherits": "2.0.3",
|
||||||
|
"minimatch": "3.0.4",
|
||||||
|
"once": "1.4.0",
|
||||||
|
"path-is-absolute": "1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"inflight": {
|
||||||
|
"version": "1.0.6",
|
||||||
|
"bundled": true,
|
||||||
|
"requires": {
|
||||||
|
"once": "1.4.0",
|
||||||
|
"wrappy": "1.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"inherits": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"bundled": true
|
||||||
|
},
|
||||||
|
"lodash": {
|
||||||
|
"version": "3.10.1",
|
||||||
|
"bundled": true
|
||||||
|
},
|
||||||
|
"minimatch": {
|
||||||
|
"version": "3.0.4",
|
||||||
|
"bundled": true,
|
||||||
|
"requires": {
|
||||||
|
"brace-expansion": "1.1.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nopt": {
|
||||||
|
"version": "3.0.6",
|
||||||
|
"bundled": true,
|
||||||
|
"requires": {
|
||||||
|
"abbrev": "1.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"once": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"bundled": true,
|
||||||
|
"requires": {
|
||||||
|
"wrappy": "1.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"os-homedir": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"bundled": true
|
||||||
|
},
|
||||||
|
"os-tmpdir": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"bundled": true
|
||||||
|
},
|
||||||
|
"osenv": {
|
||||||
|
"version": "0.1.4",
|
||||||
|
"bundled": true,
|
||||||
|
"requires": {
|
||||||
|
"os-homedir": "1.0.2",
|
||||||
|
"os-tmpdir": "1.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"path-is-absolute": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"bundled": true
|
||||||
|
},
|
||||||
|
"plist": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"bundled": true,
|
||||||
|
"requires": {
|
||||||
|
"base64-js": "0.0.8",
|
||||||
|
"util-deprecate": "1.0.2",
|
||||||
|
"xmlbuilder": "4.0.0",
|
||||||
|
"xmldom": "0.1.27"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"properties-parser": {
|
||||||
|
"version": "0.2.3",
|
||||||
|
"bundled": true
|
||||||
|
},
|
||||||
|
"q": {
|
||||||
|
"version": "1.5.0",
|
||||||
|
"bundled": true
|
||||||
|
},
|
||||||
|
"sax": {
|
||||||
|
"version": "0.3.5",
|
||||||
|
"bundled": true
|
||||||
|
},
|
||||||
|
"semver": {
|
||||||
|
"version": "5.4.1",
|
||||||
|
"bundled": true
|
||||||
|
},
|
||||||
|
"shelljs": {
|
||||||
|
"version": "0.5.3",
|
||||||
|
"bundled": true
|
||||||
|
},
|
||||||
|
"underscore": {
|
||||||
|
"version": "1.8.3",
|
||||||
|
"bundled": true
|
||||||
|
},
|
||||||
|
"unorm": {
|
||||||
|
"version": "1.4.1",
|
||||||
|
"bundled": true
|
||||||
|
},
|
||||||
|
"util-deprecate": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"bundled": true
|
||||||
|
},
|
||||||
|
"wrappy": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"bundled": true
|
||||||
|
},
|
||||||
|
"xmlbuilder": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"bundled": true,
|
||||||
|
"requires": {
|
||||||
|
"lodash": "3.10.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"xmldom": {
|
||||||
|
"version": "0.1.27",
|
||||||
|
"bundled": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"cordova-plugin-browsertab": {
|
||||||
|
"version": "0.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/cordova-plugin-browsertab/-/cordova-plugin-browsertab-0.2.0.tgz",
|
||||||
|
"integrity": "sha1-Hgf5hy4VRnpQ59FKc/79h0+u1ko="
|
||||||
|
},
|
||||||
|
"cordova-plugin-compat": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/cordova-plugin-compat/-/cordova-plugin-compat-1.2.0.tgz",
|
||||||
|
"integrity": "sha1-C8ZXVyduvZIMASzpIOJ0F3V2Nz4="
|
||||||
|
},
|
||||||
|
"cordova-plugin-deeplinks": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/cordova-plugin-deeplinks/-/cordova-plugin-deeplinks-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-xXixVrXfX9lvhMpi1qlzkiTeOmT7P5LfgqIBUCePYSutuscX+SeRGsVM38J8nhpYIefHAJqz7ULr4hT7tunUCA==",
|
||||||
|
"requires": {
|
||||||
|
"mkpath": "1.0.0",
|
||||||
|
"node-version-compare": "1.0.1",
|
||||||
|
"plist": "3.0.1",
|
||||||
|
"rimraf": "2.6.2",
|
||||||
|
"xml2js": "0.4.19"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"cordova-plugin-whitelist": {
|
||||||
|
"version": "1.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/cordova-plugin-whitelist/-/cordova-plugin-whitelist-1.3.3.tgz",
|
||||||
|
"integrity": "sha1-tehezbv+Wu3tQKG/TuI3LmfZb7Q="
|
||||||
|
},
|
||||||
|
"fs.realpath": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
|
||||||
|
},
|
||||||
|
"glob": {
|
||||||
|
"version": "7.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
|
||||||
|
"integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
|
||||||
|
"requires": {
|
||||||
|
"fs.realpath": "1.0.0",
|
||||||
|
"inflight": "1.0.6",
|
||||||
|
"inherits": "2.0.3",
|
||||||
|
"minimatch": "3.0.4",
|
||||||
|
"once": "1.4.0",
|
||||||
|
"path-is-absolute": "1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"inflight": {
|
||||||
|
"version": "1.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||||
|
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
|
||||||
|
"requires": {
|
||||||
|
"once": "1.4.0",
|
||||||
|
"wrappy": "1.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"inherits": {
|
||||||
|
"version": "2.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
||||||
|
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
|
||||||
|
},
|
||||||
|
"minimatch": {
|
||||||
|
"version": "3.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
||||||
|
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||||
|
"requires": {
|
||||||
|
"brace-expansion": "1.1.11"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mkpath": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mkpath/-/mkpath-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-67Opd+evHGg65v2hK1Raa6bFhT0="
|
||||||
|
},
|
||||||
|
"node-version-compare": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-version-compare/-/node-version-compare-1.0.1.tgz",
|
||||||
|
"integrity": "sha1-2Fv9IPCsreM1d/VmgscQnDTFUM0="
|
||||||
|
},
|
||||||
|
"once": {
|
||||||
|
"version": "1.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||||
|
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
||||||
|
"requires": {
|
||||||
|
"wrappy": "1.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"path-is-absolute": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||||
|
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
|
||||||
|
},
|
||||||
|
"plist": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/plist/-/plist-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-GpgvHHocGRyQm74b6FWEZZVRroHKE1I0/BTjAmySaohK+cUn+hZpbqXkc3KWgW3gQYkqcQej35FohcT0FRlkRQ==",
|
||||||
|
"requires": {
|
||||||
|
"base64-js": "1.3.0",
|
||||||
|
"xmlbuilder": "9.0.7",
|
||||||
|
"xmldom": "0.1.27"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"rimraf": {
|
||||||
|
"version": "2.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
|
||||||
|
"integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==",
|
||||||
|
"requires": {
|
||||||
|
"glob": "7.1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sax": {
|
||||||
|
"version": "1.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
|
||||||
|
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
|
||||||
|
},
|
||||||
|
"wrappy": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||||
|
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
|
||||||
|
},
|
||||||
|
"xml2js": {
|
||||||
|
"version": "0.4.19",
|
||||||
|
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz",
|
||||||
|
"integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==",
|
||||||
|
"requires": {
|
||||||
|
"sax": "1.2.4",
|
||||||
|
"xmlbuilder": "9.0.7"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"xmlbuilder": {
|
||||||
|
"version": "9.0.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz",
|
||||||
|
"integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0="
|
||||||
|
},
|
||||||
|
"xmldom": {
|
||||||
|
"version": "0.1.27",
|
||||||
|
"resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.27.tgz",
|
||||||
|
"integrity": "sha1-1QH5ezvbQDr4757MIFcxh6rawOk="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
24
examples/cordova-native/package.json
Normal file
24
examples/cordova-native/package.json
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
{
|
||||||
|
"name": "org.keycloak.examples.cordova",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"displayName": "Keycloak Auth",
|
||||||
|
"cordova": {
|
||||||
|
"platforms": [
|
||||||
|
"ios",
|
||||||
|
"android"
|
||||||
|
],
|
||||||
|
"plugins": {
|
||||||
|
"cordova-plugin-browsertab": {},
|
||||||
|
"cordova-plugin-deeplinks": {},
|
||||||
|
"cordova-plugin-whitelist": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"cordova-android": "^6.4.0",
|
||||||
|
"cordova-ios": "^4.5.4",
|
||||||
|
"cordova-plugin-browsertab": "^0.2.0",
|
||||||
|
"cordova-plugin-compat": "^1.2.0",
|
||||||
|
"cordova-plugin-deeplinks": "^1.1.0",
|
||||||
|
"cordova-plugin-whitelist": "^1.3.3"
|
||||||
|
}
|
||||||
|
}
|
123
examples/cordova-native/www/index.html
Normal file
123
examples/cordova-native/www/index.html
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<!--
|
||||||
|
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||||
|
~ and other contributors as indicated by the @author tags.
|
||||||
|
~
|
||||||
|
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
~ you may not use this file except in compliance with the License.
|
||||||
|
~ You may obtain a copy of the License at
|
||||||
|
~
|
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
~
|
||||||
|
~ Unless required by applicable law or agreed to in writing, software
|
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
~ See the License for the specific language governing permissions and
|
||||||
|
~ limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Authentication Example</title>
|
||||||
|
|
||||||
|
<meta http-equiv="Content-Security-Policy" content="default-src * gap://ready; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval'">
|
||||||
|
|
||||||
|
<script type="text/javascript" charset="utf-8" src="cordova.js"></script>
|
||||||
|
<script type="text/javascript" charset="utf-8" src="keycloak.js"></script>
|
||||||
|
<script type="text/javascript" charset="utf-8">
|
||||||
|
var keycloak = new Keycloak();
|
||||||
|
|
||||||
|
keycloak.onAuthSuccess = updateState;
|
||||||
|
keycloak.onAuthRefreshSuccess = updateState;
|
||||||
|
keycloak.onAuthLogout = updateState;
|
||||||
|
|
||||||
|
function updateState() {
|
||||||
|
if (keycloak.authenticated) {
|
||||||
|
document.getElementById('authenticated').style.display = 'block';
|
||||||
|
document.getElementById('not-authenticated').style.display = 'none';
|
||||||
|
|
||||||
|
document.getElementById('subject').innerText = keycloak.subject;
|
||||||
|
document.getElementById('username').innerText = keycloak.idTokenParsed.preferred_username;
|
||||||
|
document.getElementById('tokenExpires').innerText = new Date(keycloak.tokenParsed.exp * 1000).toLocaleString();
|
||||||
|
document.getElementById('tokenRefreshExpires').innerText = new Date(keycloak.refreshTokenParsed.exp * 1000).toLocaleString();
|
||||||
|
document.getElementById('token').innerText = JSON.stringify(keycloak.tokenParsed, null, ' ');
|
||||||
|
document.getElementById('idToken').innerText = JSON.stringify(keycloak.idTokenParsed, null, ' ');
|
||||||
|
} else {
|
||||||
|
document.getElementById('authenticated').style.display = 'none';
|
||||||
|
document.getElementById('not-authenticated').style.display = 'block';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function error() {
|
||||||
|
document.getElementById('authenticated').style.display = 'none';
|
||||||
|
document.getElementById('not-authenticated').style.display = 'block';
|
||||||
|
document.getElementById('error').innerText = 'Failed to initialize Keycloak adapter';
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener("deviceready", function() {
|
||||||
|
keycloak.init({
|
||||||
|
adapter: 'cordova-native',
|
||||||
|
responseMode: 'query',
|
||||||
|
onLoad: 'check-sso',
|
||||||
|
redirectUri: 'android-app://org.keycloak.examples.cordova/https/keycloak-cordova-example.github.io/login'
|
||||||
|
}).success(updateState).error(error);
|
||||||
|
}, false);
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
td {
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr.odd td {
|
||||||
|
background-color: #eee;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="authenticated" style="display: none;">
|
||||||
|
<div>
|
||||||
|
<button onclick="keycloak.logout()">Log out</button>
|
||||||
|
<button onclick="keycloak.updateToken()">Refresh token</button>
|
||||||
|
<button onclick="keycloak.updateToken(9999)">Force Refresh token</button>
|
||||||
|
<button onclick="keycloak.accountManagement()">Manage account</button>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td>Subject</td>
|
||||||
|
<td id="subject"></td>
|
||||||
|
</tr>
|
||||||
|
<tr class="odd">
|
||||||
|
<td>Username</td>
|
||||||
|
<td id="username"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Token expires</td>
|
||||||
|
<td id="tokenExpires"></td>
|
||||||
|
</tr>
|
||||||
|
<tr class="odd">
|
||||||
|
<td>Refresh token expires</td>
|
||||||
|
<td id="tokenRefreshExpires"></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Token</td>
|
||||||
|
<td><pre id="token"></pre></td>
|
||||||
|
</tr>
|
||||||
|
<tr class="odd">
|
||||||
|
<td>ID Token</td>
|
||||||
|
<td><pre id="idToken"></pre></td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="not-authenticated" style="display: none;">
|
||||||
|
<div>
|
||||||
|
<button onclick="keycloak.login()">Log in</button>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p id="error">Not authenticated</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
Loading…
Reference in a new issue