I have a webapp that its backend is written in Python and renders some html for the frontend users.
What I would like to achieve is:
when a user makes a POST request to /token, the backend replies with a JSON document {"access_token": access_token, "token_type": "bearer"}; this is already in place
after the above takes place, every subsequent request / navigation to the webapp, should set a header named Authorization equal to Bearer <access_token> to every GET, POST, etc. request that it does; not important for the time being
can you advise and describe how to maintain a single variable client-side called access_token that its default value is null, but when doing POST to /token, then the variable access_token is initialised and never changes through navigation, unless the end user makes another POST request to /token again to reset the access_token to the new value ?
I am not familiar with jQuery or javascript much. Can you suggest how to initialise, set, reset a variable (and just print it, for example, using console.log) based on the background information above ?
You can store the token in local storage, or in cookies, either would work. Then, when you go to make an ajax call, you'll retrieve the value from whichever you used, and add it to the outgoing ajax request. How exactly you do that willl depend on what specific ajax implementation you use. For example google "add auth token to jquery.ajax" and you'll find the right syntax for that library
Something like this would work:
// do initial login and get token
var token = response.access_token;
// store it in local storage
localStorage.setItem('apiKey', token);
// ... navigate around and what not...
// later, when you need to make another call, get the token
var token = localStorage.getItem('apiKey');
$.ajax({
url: url,
method: "POST",
dataType: "json",
//.. other props as needed...
beforeSend: function (xhr) {
/* set the Authorization header with the token */
xhr.setRequestHeader("Authorization", "Bearer " + token);
},
success: function (data) {
// do something cool with data
},
error: function (jqXHR, textStatus, errorThrown) {
// handle errors ...
}
});
I am trying to play Scorm contents via Sakai LMS from my application. For doing that, I want to get the user session after logging in to Sakai and pass it for any other calls. I am able to get the user session cookie after login from Sakai via a rest call, but I am not able to pass the "Set-cookie" in the header or Store the cookie manually so that I will be able to use them to call other URL's that plays the Scorm or invokes other functionalities for the current user.
How can I use the cookie returned by the getSession API to do other functionalities for the logged in user?
I have tried passing the response header from the login to make the next API call.
I have tried forming the Session and adding it to the header after removing the 'HTML only' like "SAKAI2SESSIONID="+session+".domain; Path=/;"
I have tried passing the session id and cookie in the response and manually storing it in the local storage
-----1------
HttpPost httpPost = new HttpPost(url);
httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded");
httpPost.setEntity(new UrlEncodedFormEntity(params));
HttpResponse response = client.execute(httpPost);
Header[] headers = response.getAllHeaders();
String session=EntityUtils.toString(response.getEntity());
response.setHeader("Set-Cookie","SAKAI2SESSIONID="+session);
----3----
function getSessionId() {
let data = {
password: "pass",
userId: "user"
}
fetch('http:ldomain/sakai/getSession', {
method: 'POST',
body: JSON.stringify(data),
headers:{
'Content-Type': 'application/json',
"Access-Control-Allow-Origin": "*"
},
})
.then(response => response.json())
.then(response => {
localStorage.setItem('SAKAI2SESSIONID', response.entity.cookie[0])
document.cookie= response.entity.cookie[0];
})
.catch(error => console.error('Error:', error))
}
even though I tried all these when I try to hit Scorm URL after doing this, it redirects me to the login page again.
I have one GET endpoint.
It has HTTP Basic Authentication enabled. I want to create a GET request to the given end point.
https://example.com/api GET
User Name :- admin
Password :- admin
My Code :-
$scope.listData = function() {
$http.get('https://example.com/api').then(function(response) {
$scope.items = response.data;
});
}
What is the recommended way to pass the authentication?
Second argument for the GET is the header part. For ex.
$http.get('www.google.com/someapi', {
headers: {'Authorization': 'Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ=='}
}).then()..;
the recommended method is http-interceptors.
what interceptor do, you can assume its a hook which call on every api request and response, once you write it, it will automatically add token in every api request. below is the url you read the article.
Angular Authentication: Using the Http Client and Http Interceptors
I am working on an internal web application at work. In IE10 the requests work fine, but in Chrome all the AJAX requests (which there are many) are sent using OPTIONS instead of whatever defined method I give it. Technically my requests are "cross domain." The site is served on localhost:6120 and the service I'm making AJAX requests to is on 57124. This closed jquery bug defines the issue, but not a real fix.
What can I do to use the proper http method in ajax requests?
Edit:
This is in the document load of every page:
jQuery.support.cors = true;
And every AJAX is built similarly:
var url = 'http://localhost:57124/My/Rest/Call';
$.ajax({
url: url,
dataType: "json",
data: json,
async: true,
cache: false,
timeout: 30000,
headers: { "x-li-format": "json", "X-UserName": userName },
success: function (data) {
// my success stuff
},
error: function (request, status, error) {
// my error stuff
},
type: "POST"
});
Chrome is preflighting the request to look for CORS headers. If the request is acceptable, it will then send the real request. If you're doing this cross-domain, you will simply have to deal with it or else find a way to make the request non-cross-domain. This is why the jQuery bug was closed as won't-fix. This is by design.
Unlike simple requests (discussed above), "preflighted" requests first
send an HTTP request by the OPTIONS method to the resource on the
other domain, in order to determine whether the actual request is safe
to send. Cross-site requests are preflighted like this since they may
have implications to user data. In particular, a request is
preflighted if:
It uses methods other than GET, HEAD or POST. Also, if POST is used to send request data with a Content-Type other than
application/x-www-form-urlencoded, multipart/form-data, or text/plain,
e.g. if the POST request sends an XML payload to the server using
application/xml or text/xml, then the request is preflighted.
It sets custom headers in the request (e.g. the request uses a header such as X-PINGOTHER)
Based on the fact that the request isn't sent on the default port 80/443 this Ajax call is automatically considered a cross-origin resource (CORS) request, which in other words means that the request automatically issues an OPTIONS request which checks for CORS headers on the server's/servlet's side.
This happens even if you set
crossOrigin: false;
or even if you ommit it.
The reason is simply that localhost != localhost:57124. Try sending it only to localhost without the port - it will fail, because the requested target won't be reachable, however notice that if the domain names are equal the request is sent without the OPTIONS request before POST.
I agree with Kevin B, the bug report says it all. It sounds like you are trying to make cross-domain ajax calls. If you're not familiar with the same origin policy you can start here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Same_origin_policy_for_JavaScript.
If this is not intended to be a cross-domain ajax call, try making your target url relative and see if the problem goes away. If you're really desperate look into the JSONP, but beware, mayhem lurks. There really isn't much more we can do to help you.
If it is possible pass the params through regular GET/POST with a different name and let your server side code handles it.
I had a similar issue with my own proxy to bypass CORS and I got the same error of POST->OPTION in Chrome. It was the Authorization header in my case ("x-li-format" and "X-UserName" here in your case.) I ended up passing it in a dummy format (e.g. AuthorizatinJack in GET) and I changed the code for my proxy to turn that into a header when making the call to the destination. Here it is in PHP:
if (isset($_GET['AuthorizationJack'])) {
$request_headers[] = "Authorization: Basic ".$_GET['AuthorizationJack'];
}
In my case I'm calling an API hosted by AWS (API Gateway). The error happened when I tried to call the API from a domain other than the API own domain. Since I'm the API owner I enabled CORS for the test environment, as described in the Amazon Documentation.
In production this error will not happen, since the request and the api will be in the same domain.
I hope it helps!
As answered by #Dark Falcon, I simply dealt with it.
In my case, I am using node.js server, and creating a session if it does not exist. Since the OPTIONS method does not have the session details in it, it ended up creating a new session for every POST method request.
So in my app routine to create-session-if-not-exist, I just added a check to see if method is OPTIONS, and if so, just skip session creating part:
app.use(function(req, res, next) {
if (req.method !== "OPTIONS") {
if (req.session && req.session.id) {
// Session exists
next();
}else{
// Create session
next();
}
} else {
// If request method is OPTIONS, just skip this part and move to the next method.
next();
}
}
"preflighted" requests first send an HTTP request by the OPTIONS method to the resource on the other domain, in order to determine whether the actual request is safe to send. Cross-site requests
https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
Consider using axios
axios.get( url,
{ headers: {"Content-Type": "application/json"} } ).then( res => {
if(res.data.error) {
} else {
doAnything( res.data )
}
}).catch(function (error) {
doAnythingError(error)
});
I had this issue using fetch and axios worked perfectly.
I've encountered a very similar issue. I spent almost half a day to understand why everything works correctly in Firefox and fails in Chrome. In my case it was because of duplicated (or maybe mistyped) fields in my request header.
Use fetch instead of XHR,then the request will not be prelighted even it's cross-domained.
$.ajax({
url: '###',
contentType: 'text/plain; charset=utf-8',
async: false,
xhrFields: {
withCredentials: true,
crossDomain: true,
Authorization: "Bearer ...."
},
method: 'POST',
data: JSON.stringify( request ),
success: function (data) {
console.log(data);
}
});
the contentType: 'text/plain; charset=utf-8', or just contentType: 'text/plain', works for me!
regards!!
After a POST request is sent from the browser to the /generate url in the server, I want to create a string and save it as a cookie. When a GET request is later sent from the browser to the /retrieve url in the server, I want to send that string as a response to the client.
Here is what I tried:
routes.js
const Router = require('koa-router')
const router = new Router()
router.post('/generate', function * () {
this.cookies.set('generatedString', 'example')
this.response.body = 'String saved as cookie!'
})
router.get('/retrieve', function * () {
const cookie = this.cookies.get('generatedString')
console.log(cookie) // undefined!
this.response.body = cookie
})
Why does doing this.cookies.get('generatedString') return undefined even though the POST request handler has already run and should have set that cookie? Any help would be appreciated!
EDIT: In case it is of importance, I thought it would be worth mentioning that I am using the fetch API to make the POST and GET requests.
In case it is of importance, I thought it would be worth mentioning that I am using the fetch API to make the POST and GET requests.
The fetch API mentions that "By default, fetch won't send any cookies to the server, resulting in unauthenticated requests if the site relies on maintaining a user session."
If you want fetch to send cookies, you will need to add an option to the request you send out called credentials and set it to a value of include.
Example POST request:
const request = {
method: 'POST',
credentials: 'include',
headers: ...,
body: ...
}
fetch('/generate', request).then(...)
Example GET request:
fetch('/retrieve', { credentials: 'include' }).then(...)