diff --git a/adapters/oidc/js/src/main/resources/keycloak.d.ts b/adapters/oidc/js/src/main/resources/keycloak.d.ts
index 51d31919cd..eed2bf48e7 100644
--- a/adapters/oidc/js/src/main/resources/keycloak.d.ts
+++ b/adapters/oidc/js/src/main/resources/keycloak.d.ts
@@ -29,7 +29,7 @@ export = Keycloak;
declare function Keycloak(config?: string|{}): Keycloak.KeycloakInstance;
declare namespace Keycloak {
- type KeycloakAdapterName = 'cordova'|'default' | any;
+ type KeycloakAdapterName = 'cordova' | 'cordova-native' |'default' | any;
type KeycloakOnLoad = 'login-required'|'check-sso';
type KeycloakResponseMode = 'query'|'fragment';
type KeycloakResponseType = 'code'|'id_token token'|'code id_token token';
@@ -98,6 +98,12 @@ declare namespace Keycloak {
*/
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.
* @default standard
diff --git a/adapters/oidc/js/src/main/resources/keycloak.js b/adapters/oidc/js/src/main/resources/keycloak.js
index 0edde89754..8b147bf9a0 100755
--- a/adapters/oidc/js/src/main/resources/keycloak.js
+++ b/adapters/oidc/js/src/main/resources/keycloak.js
@@ -46,11 +46,10 @@
kc.authenticated = false;
callbackStorage = createCallbackStorage();
+ var adapters = ['default', 'cordova', 'cordova-native'];
- if (initOptions && initOptions.adapter === 'cordova') {
- adapter = loadAdapter('cordova');
- } else if (initOptions && initOptions.adapter === 'default') {
- adapter = loadAdapter();
+ if (initOptions && adapters.indexOf(initOptions.adapter) > -1) {
+ adapter = loadAdapter(initOptions.adapter);
} else if (initOptions && typeof initOptions.adapter === "object") {
adapter = initOptions.adapter;
} else {
@@ -106,6 +105,10 @@
if (initOptions.timeSkew != null) {
kc.timeSkew = initOptions.timeSkew;
}
+
+ if(initOptions.redirectUri) {
+ kc.redirectUri = initOptions.redirectUri;
+ }
}
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;
}
diff --git a/examples/cordova-native/.gitignore b/examples/cordova-native/.gitignore
new file mode 100644
index 0000000000..3ac935ae6e
--- /dev/null
+++ b/examples/cordova-native/.gitignore
@@ -0,0 +1,6 @@
+platforms
+plugins
+www/keycloak.js
+www/keycloak.json
+node_modules
+ul_web_hooks
diff --git a/examples/cordova-native/README.md b/examples/cordova-native/README.md
new file mode 100644
index 0000000000..0510ba8c91
--- /dev/null
+++ b/examples/cordova-native/README.md
@@ -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'.
diff --git a/examples/cordova-native/config.xml b/examples/cordova-native/config.xml
new file mode 100644
index 0000000000..0a0d962a58
--- /dev/null
+++ b/examples/cordova-native/config.xml
@@ -0,0 +1,25 @@
+
+
+ Keycloak Auth
+ Keycloak Cordova Example
+ Keycloak Team
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/cordova-native/example-realm.json b/examples/cordova-native/example-realm.json
new file mode 100755
index 0000000000..131ccbd511
--- /dev/null
+++ b/examples/cordova-native/example-realm.json
@@ -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"]
+ }
+ ]
+ }
+}
diff --git a/examples/cordova-native/package-lock.json b/examples/cordova-native/package-lock.json
new file mode 100644
index 0000000000..63bb61364d
--- /dev/null
+++ b/examples/cordova-native/package-lock.json
@@ -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="
+ }
+ }
+}
diff --git a/examples/cordova-native/package.json b/examples/cordova-native/package.json
new file mode 100644
index 0000000000..796ff56ffa
--- /dev/null
+++ b/examples/cordova-native/package.json
@@ -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"
+ }
+}
\ No newline at end of file
diff --git a/examples/cordova-native/www/index.html b/examples/cordova-native/www/index.html
new file mode 100644
index 0000000000..67b0db823d
--- /dev/null
+++ b/examples/cordova-native/www/index.html
@@ -0,0 +1,123 @@
+
+
+
+
+
+ Authentication Example
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Subject |
+ |
+
+
+ Username |
+ |
+
+
+ Token expires |
+ |
+
+
+ Refresh token expires |
+ |
+
+
+ Token |
+ |
+
+
+ ID Token |
+ |
+
+
+
+
+
+
+
+