I have a piece of code working with keycloak and JS.
The code working perfectly except refresh token method have to call externally when the token is expired. How can I refresh token automatically when expired.
var keycloak = Keycloak('keycloak.json');
keycloak.init({ onLoad: 'login-required' })
.success(reloadData)
.error(function(errorData) {
document.getElementById('customers').innerHTML = '<b>Failed to load data. Error: ' + JSON.stringify(errorData) + '</b>';
});
var loadData = function () {
document.getElementById('subject').innerHTML = keycloak.subject;
if (keycloak.idToken) {
document.getElementById('profileType').innerHTML = 'IDToken';
document.getElementById('username').innerHTML = keycloak.idTokenParsed.preferred_username;
document.getElementById('email').innerHTML = keycloak.idTokenParsed.email;
document.getElementById('name').innerHTML = keycloak.idTokenParsed.name;
document.getElementById('givenName').innerHTML = keycloak.idTokenParsed.given_name;
document.getElementById('familyName').innerHTML = keycloak.idTokenParsed.family_name;
} else {
keycloak.loadUserProfile(function() {
document.getElementById('profileType').innerHTML = 'Account Service';
document.getElementById('username').innerHTML = keycloak.profile.username;
document.getElementById('email').innerHTML = keycloak.profile.email;
document.getElementById('name').innerHTML = keycloak.profile.firstName + ' ' + keycloak.profile.lastName;
document.getElementById('givenName').innerHTML = keycloak.profile.firstName;
document.getElementById('familyName').innerHTML = keycloak.profile.lastName;
}, function() {
document.getElementById('profileType').innerHTML = 'Failed to retrieve user details. Please enable claims or account role';
});
}
var url = '/database/customers';
var req = new XMLHttpRequest();
req.open('GET', url, true);
req.setRequestHeader('Accept', 'application/json');
req.setRequestHeader('Authorization', 'Bearer ' + keycloak.token);
req.onreadystatechange = function () {
if (req.readyState == 4) {
if (req.status == 200) {
var users = JSON.parse(req.responseText);
var html = '';
for (var i = 0; i < users.length; i++) {
html += '<p>' + users[i] + '</p>';
}
document.getElementById('customers').innerHTML = html;
console.log('finished loading data');
}
}
}
req.send();
};
var loadFailure = function () {
document.getElementById('customers').innerHTML = '<b>Failed to load data. Check console log</b>';
};
var reloadData = function () {
keycloak.updateToken(10)
.success(loadData)
.error(function() {
document.getElementById('customers').innerHTML = '<b>Failed to load data. User is logged out.</b>';
});
}
I know it's very late, but this answer is just for a future reference.
Don't know if it's just new and this handler was not implemented in 2017 but I use keycloak.onTokenExpired to do this.
Just an example:
keycloak.onTokenExpired = () => {
console.log('token expired', keycloak.token);
keycloak.updateToken(30).success(() => {
console.log('successfully get a new token', keycloak.token);
...
}).error(() => {...});
}
This is only works in Standard flow or Hybrid. There is no possibility to refresh token during implicit flow.
Token (Access Token Lifespan) will be refreshed as long as refreshed token (SSO Session Idle) has not expired. This will work for the duration of SSO Session Max.
Example Token (Access Token Lifespan) will expire in 2 min you can refresh it during 5 min with refreshed token (SSO Session Idle). And it will work maximum during 10 hours SSO Session Max
Access Token Lifespan could be overwritten in Clients (see right nav) Settings tab scroll down to Advanced Settings
Related
I am trying to catch the specific error when a certain API key expires or it reaches its daily response limit(assuming 1000 per day).
const moviesearchEngine=()=>{
let searchBox = document.querySelector('.searchBox');
let movieTitle = document.querySelector('.movieTitle');
let yearofRelease = document.querySelector('.yearofRelease');
let genre = document.querySelector('.genre');
let director = document.querySelector('.director');
let plot = document.querySelector('.plot');
const apiCall = ()=>{
let params = new URLSearchParams({
t:searchBox.value,
apikey:`key`
})
let api = `http://www.omdbapi.com/?${params}`;
//fetching the api orelse showing the error
fetch(api).then((response)=>{
return response.json();
}).then((data)=>{
//assigning the data to variable
console.log(data)
})
}
apiCall();
}
Please Go through your desired API's documention and you would be looking for this sort of information mentioned in the Usage limits section of this api page. If you fail to find anything useful then please contact the support of your desired API.
Then you can proceed like this -
var endpoint = 'http://ip-api.com/json/?fields=status,message,countryCode';
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var response = JSON.parse(this.responseText);
if(response.status !== 'success') {
console.log('query failed: ' + response.message);
return
}
// Redirect
if(response.countryCode == "US") {
window.location.replace("https://google.com/");
}
if(response.countryCode == "CA") {
window.location.replace("https://google.ca/");
}
}
};
xhr.open('GET', endpoint, true);
xhr.send();
Source
I have a server that consistently updates a JSON file. Tho the code I setup bellow (javascript) reads the JSON file and shows it to the client always refreshes the page.
I would like to know how I would be able to read my JSON file every time it's updated without refreshing the web page.
From what I looked up, it seems that I'll have to use AJAX to get this done. But couldn't find much else. Or should I make any update on my JSON file?
This is the index.html code I'm using to get the data from my archive.json file:
<script>
fetch('archive.json')
.then(function (response) {
return response.json();
})
.then(function (data) {
appendData(data);
})
.catch(function (err) {
console.log('error: ' + err);
});
function appendData(data) {
console.log(data.velas.length);
var mainContainer = document.getElementById("myData");
for (var i = 0; i < data.velas.length; i++) {
var div = document.createElement("div");
div.innerHTML = 'Tempo: ' + data.velas[i].tempo;
mainContainer.appendChild(div);
}
}
</script>
Thanks for any help!
You can try this, i have explained everything in code comment
<script>
const REFRESH_INTERVAL = 5; // 5 seconds
var mainContainer = document.getElementById("myData");
async function appendData() {
// make the request
const response = await fetch('archive.json');
const data = await response.json();
// check the data response
if(data == undefined && data == null) return
// manipulate DOM
var mainContainer = document.getElementById("myData");
mainContainer.innerHTML = '' // clear the content of the previous mainContainer
for (var i = 0; i < data.velas.length; i++) {
var div = document.createElement("div");
div.innerHTML = 'Tempo: ' + data.velas[i].tempo;
mainContainer.appendChild(div);
}
}
setInterval(() => { // send a request to server each 5 seconds (REFRESH_INTERVAL) <- you can change it here
appendData()
}, REFRESH_INTERVAL * 1000)
</script>
I hope I understood your question correctly.
document.querySelector('button').addEventListener('click',()=>{
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
document.querySelector('.get').innerHTML=`${JSON.parse(this.responseText).ip}`
};
}
xhttp.open("GET", "https://ipapi.co/json/", true);
xhttp.send();
})
<button>Get</button>
<div class="get">
</div>
Just acknowledge my mistake of it refreshing not because of JSON nor AJAX codes... but because I was running it on a local server. So it would refresh anyway.
But adilson's respond to the topic with a timer completed what I needed:
https://stackoverflow.com/a/68090848/16179486
Thanks for the help guys!
I am implementing Firebase Web Notification using Firebase.
The whole process is:
There are two files: a) generate-token.js b) firebase-messaging.sw.js
Permission to get access token( By calling requestPermission).
After clicking Allow, token is generated.
An Ajax call is made to backend service to save the token correspond to that browser.
We have separate module for Notification-sender and Notification-Manager to schedule and send notification.
firebase-messaging.sw.js is at root. It is called when notification is called.
There are 2 main methods for this:
initMessaging.setBackgroundMessageHandler(function (payload) {
)}; ( For background handling of message)
and
messaging.onMessage(function(payload) {}); : This method is in generate-token.js for receiving foreground message.
When notification is received, an ajax call is made to api to track notification with actionId=1 and for clicking notification actionId=3.
My questions:
In step 1, once I make an ajax call to save the token, I have to reuse that token in my methods of firebase-messaging.sw.js to hit track api (Track api require token and deviceId)
Currently, I am making device_id using userAgent, which may clash with some other machine. Is there a better way?
How can I reuse my token, as service-worker dont have access to local storage, DOM, cookies,etc.?
My code:
generate-token.js:
firebase.initializeApp(config);
const messaging=firebase.messaging();
var postURL=null;
var gcmId=null;
var id=getUniqueId();
var id1=id.split('.').join("");
if ('serviceWorker' in navigator) {
// Register service worker
navigator.serviceWorker.register('/firebase-messaging-sw.js').then(function (reg) {
console.log("SW registration succeeded. Scope is " + reg.scope);
console.log("Updating service worker" +reg.update());
}).catch(function (err) {
console.error("SW registration failed with error " + err);
});
}
messaging.onMessage(function(payload) {
console.log("OnMessage called app is in foreground");
//tracking notification with actionid=1;
trackNotification(payload.data,1,postURL,gcmId);
});
function requestPermission(url) {
console.log('Requesting permission...');
postURL=url;
var firebaseRefUrl=firebase.database().ref().child(location.host.split('.').join("")+"/" + "url");
firebaseRefUrl.set(url);
messaging.requestPermission()
.then(function () {
console.log('Notification permission granted.');
return messaging.getToken();
})
.then(function(token){
userAction(token,url);
var firebaseRefToken=firebase.database().ref().child(location.host.split('.').join("") + "/" + id1);
firebaseRefToken.set(token);
gcmId=token;
})
.catch(function (err) {
console.log('Unable to get permission for notification.', err);
});
}
function getUniqueId(){
var Sys = {};
var ua = navigator.userAgent.toLowerCase();
return ua;
}
function userAction(token,url) {
try{
console.log("Calling wrapper interface to save gcm_id");
var obj = new Object();
obj.deviceId =getUniqueId();
obj.token=token;
var jsonString= JSON.stringify(obj);
var xhttp = new XMLHttpRequest();
xhttp.open("POST", url+ "/registerGCM", true);
xhttp.setRequestHeader("Content-type", "application/json");
xhttp.send(jsonString);
xhttp.onreadystatechange = function() {
if(xhttp.readyState == XMLHttpRequest.DONE && xhttp.status == 200) {
var jsonDeviceId=JSON.parse(xhttp.responseText);
localStorage.setItem("deviceId",jsonDeviceId.deviceId);
}
}
}catch(error) {
console.log('Error while calling apis.', error);
}}
firebase-messaging.sw.js:
firebase.initializeApp(config);
var click=null;
var url;
var token;
var obj=new Object();
//Initialise firebase messaging
const initMessaging = firebase.messaging();
var id=getUniqueId();
var id1=id.split('.').join("");
var firebaseRefToken=firebase.database().ref().child(location.host.split('.').join("") + "/" + id1);
firebaseRefToken.on('value',function(data){
token=data.val();
});
var firebaseRefUrl=firebase.database().ref().child(location.host.split('.').join("") +"/" + "url");
firebaseRefUrl.on('value',function(data){
url=data.val();
});
//Background push notification handler. It fires up when the browser or web page in which push notification is activated are closed.
initMessaging.setBackgroundMessageHandler(function (payload) {
//console.log("In background");
console.log("Tracking notification when the app is in background");
var gcmId;
var tokenRefCheck=firebase.database().ref().child(location.host.split('.').join("") + "/" + id1);
tokenRefCheck.on('value',function(data){
gcmId=data.val();
});
trackNotification(obj.data,1,url,null);
});
//Displays incoming push notification
self.addEventListener('push', function (event) {
console.log('Push Notification Received.');
var eventData = event.data.text();
obj = JSON.parse(eventData); //Parse the received JSON object.
//printing payload
console.log("PAyload is " + JSON.stringify(obj,2,null));
const title = obj.data.title;
click=obj.data.targetActionData;
const options = {
body: obj.data.body,
icon: obj.data.icon,
click_action:obj.data.targetActionData
};
event.preventDefault();
event.waitUntil(self.registration.showNotification(title, options));
});
//Take action when a user clicks on the received notification.
self.addEventListener('notificationclick', function (event) {
console.log("Notification clicked");
event.notification.close();
event.preventDefault(); // prevent the browser from focusing the Notification's tab
trackNotification(obj.data,3,url,null);
event.waitUntil(
clients.openWindow(click)
);
});
self.addEventListener('notificationclose', function (event) {
console.log("Notification closed");
event.notification.close();
event.preventDefault(); // prevent the browser from focusing the Notification's tab
trackNotification(obj.data,2,url,null);
});
function trackNotification(data,actionId,url,gcmId) {
try{
var obj=new Object();
console.log("Calling track notification api to save the data");
if(actionId===1){
console.log("Tracking for receving notification");
}
if(actionId===2){
console.log("Tracking for closing notification");
}
if(actionId===3){
console.log("Tracking for clicking notification");
}
obj.deviceId =getUniqueId();
obj.campaignId=data.campaignId;
obj.actionTime=new Date();
if(gcmId!=null)
obj.token=gcmId;
else
obj.token=token;
obj.actionId=actionId;
obj.scheduleId=data.scheduleId;
var jsonString= JSON.stringify(obj,2,null);
/*xhttp.open("POST", postURL+ "/trackNotification", true);
xhttp.setRequestHeader("Content-type", "application/json");
xhttp.send(jsonString);*/
console.log("Payload" + jsonString);
fetch(url + "/trackNotification", {
method: 'post',
headers: {
"Content-type": "application/json; charset=UTF-8"
},
body: jsonString
})
.then(function (data) {
})
.catch(function (error) {
console.log('Request failed', error);
});
}catch(error) {
console.log('Error while calling apis.', error);
}}
function getUniqueId(){
var Sys = {};
var ua = navigator.userAgent.toLowerCase();
return ua;
}
I am using Firebase Database, and save the token with useragent as a key, but it will sure collide with some other device.
You can save the data in the service worker cache.
The Service Worker API comes with a Cache interface, that lets you
create stores of responses keyed by request. While this interface was
intended for service workers it is actually exposed on the window, and
can be accessed from anywhere in your scripts. The entry point is
caches.
https://developers.google.com/web/ilt/pwa/caching-files-with-service-worker
I'm building a chrome extension that needs to allow user authentication through facebook. I've been following the "manual login flow" since the facebook Javascript SDK doesn't work in extensions. Thus far, I've allowed users to click a link that gets permissions and returns an access token:
index.html
Sign In with Facebook
index.js
function onFacebookLogin(){
if (localStorage.getItem('accessToken')) {
chrome.tabs.query({}, function(tabs) { // get all tabs from every window
for (var i = 0; i < tabs.length; i++) {
if (tabs[i].url.indexOf(successURL) !== -1) {
// below you get string like this: access_token=...&expires_in=...
var params = tabs[i].url.split('#')[1];
// in my extension I have used mootools method: parseQueryString. The following code is just an example ;)
var accessToken = params.split('&')[0];
accessToken = accessToken.split('=')[1];
localStorage.setItem('accessToken', accessToken);
chrome.tabs.remove(tabs[i].id);
console.log(accessToken)
userSignedIn = true
findFacebookName();
}
}
});
}
}
chrome.tabs.onUpdated.addListener(onFacebookLogin);
^ ALL OF THIS WORKS. Everytime a user "logs in" the localstorage.accessToken is updated. Then, I get to the point where I try to retrieve user data by inspecting the token through the api:
var client_token = '{MY_CLIENT_TOKEN(NOT CLIENT_ID}'
var inspectTokenUrl = 'https://graph.facebook.com/debug_token?input_token=' +
localStorage.accessToken +
'&access_token=' +
client_token
function findFacebookName(){
var xhr = new XMLHttpRequest();
xhr.open("GET", inspectTokenUrl, true);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
}
}
xhr.send();
}
But this returns a 190 oauth error. What am I doing wrong? What is the correct way to request the users email address using the access_token?
Hy
I need to find the current user from my SharePoint.
I have tried many things :
SP.Utilities.PrincipalInfo.get_loginName()
_spPageContextInfo.userId
...
At all times, I have the same result Undefined =(
When using CSOM API to retrieve current user object,wrap your code inside
SP.SOD.executeOrDelayUntilScriptLoaded method to make sure that the specified code is executed after SharePoint JS library (sp.js) is loaded:
SP.SOD.executeOrDelayUntilScriptLoaded(function(){
//your code goes here..
}, 'sp.js');
How to retrieve current user object using CSOM API
function getCurrentUser(success,error)
{
var ctx = SP.ClientContext.get_current();
var web = ctx.get_web();
var currentUser = web.get_currentUser();
ctx.load(currentUser);
ctx.executeQueryAsync(function(){
success(currentUser);
},
error);
}
Usage
SP.SOD.executeOrDelayUntilScriptLoaded(function(){
getCurrentUser(
function(currentUser){
console.log(currentUser.get_loginName());
},
function(sender, args)
{
console.log('Request failed ' + args.get_message() + ':'+ args.get_stackTrace());
});
}, 'sp.js');
The answer is probably here. The only thing i changed is getting LoginName instead of Title:
https://stackoverflow.com/a/21002895/1680288
var userid= _spPageContextInfo.userId;
var requestUri = _spPageContextInfo.webAbsoluteUrl + "/_api/web/getuserbyid(" + userid + ")";
var requestHeaders = { "accept" : "application/json;odata=verbose" };
$.ajax({
url : requestUri,
contentType : "application/json;odata=verbose",
headers : requestHeaders,
success : onSuccess,
error : onError
});
function onSuccess(data, request){
var loginName = data.d.LoginName;
alert(loginName);
}
function onError(error) {
alert("error");
}
If you are getting undefined.. Maybe you are not authenticated or did not include some relevant javascript files in your master page.
Without jquery:
var userid= _spPageContextInfo.userId;
var requestUri = _spPageContextInfo.webAbsoluteUrl + "/_api/web/getuserbyid(" + userid + ")";
function createXMLHttp() {
//If XMLHttpRequest is available then using it
if (typeof XMLHttpRequest !== undefined) {
return new XMLHttpRequest;
//if window.ActiveXObject is available than the user is using IE...so we have to create the newest version XMLHttp object
} else if (window.ActiveXObject) {
var ieXMLHttpVersions = ['MSXML2.XMLHttp.5.0', 'MSXML2.XMLHttp.4.0', 'MSXML2.XMLHttp.3.0', 'MSXML2.XMLHttp', 'Microsoft.XMLHttp'],
xmlHttp;
//In this array we are starting from the first element (newest version) and trying to create it. If there is an
//exception thrown we are handling it (and doing nothing ^^)
for (var i = 0; i < ieXMLHttpVersions.length; i++) {
try {
xmlHttp = new ActiveXObject(ieXMLHttpVersions[i]);
return xmlHttp;
} catch (e) {
}
}
}
}
function getData() {
var xmlHttp = createXMLHttp();
xmlHttp.open('get', requestUri , true);
xmlHttp.setRequestHeader("Content-Type", "application/json;odata=verbose");
xmlHttp.setRequestHeader("accept", "application/json;odata=verbose");
xmlHttp.send(null);
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState === 4) {
if (xmlHttp.status === 200) {
var data = JSON.parse(xmlHttp.responseText);
var loginName = data.d.LoginName;
alert(loginName);
} else {
}
} else {
//still processing
}
};
}
getData();