I've created rest API in springboot that upon sending valid credentials returns jwt access token and saves refresh token in httpOnly cookie, when I send GET request to the API that uses cookie in postman it works just fine but when I try to fetch in react API returns error that indicates that there is no cookies
error_message: "Cannot read the array length because "array" is null"
So do I have to specify domain name If yes how do I do it while working on localhost (springboot is working on localhost:8080 and react localhost:3000).
How I currently create cookie:
public static Cookie createRefreshCookie(String refresh_token) {
Cookie jwtRefreshCookie = new Cookie("refresh_token", refresh_token);
jwtRefreshCookie.setMaxAge(2678400);
jwtRefreshCookie.setHttpOnly(true);
jwtRefreshCookie.setPath("/");
return jwtRefreshCookie;
}
Problem was caused by my fetch request in react that contained header withCredentials: true from library axios insead of fetch implementation of header credentials:"include".
Related
I am using spring security with angular 6. When i login using basic Auth server sends a cookie JessionID with response. I want to send this cookie with other request for authentication purpose but it gives me error Refused to set unsafe header 'Cookie' . When i hit the same endpoint from postman with same cookie in header it works.
Below is the method in angular:
Note: Currently i am manually adding it with headers.
private heroesUrl = 'http://localhost:8080/hi';
header = new HttpHeaders().set("Cookie", "JSESSIONID=A2A75EC9A3E1172D60060C6E708549B5");
getMessage() :Observable<Message>{
return this.http.get<Message>(this.heroesUrl,{headers:this.header});
}
Response which i get when i login using basic Auth
You can't do this, cause the browser doesn't allow you to do it. Let me describe the problem here:
Did you notice the Set-Cookie: JSESSIONID=......; Path=/; HttpOnly in your response headers? Well, The problem is the HttpOnly flag. Actually :) it's not a problem, it's a feature to prevent attacks that aim to steal your browser cookies:
HttpOnly is a flag added to cookies that tell the browser not to display the cookie through client-side scripts (document.cookie and others). ... When you set a cookie with the HttpOnly flag, it informs the browser that this special cookie should only be accessed by the server
So the browser doesn't allow any javascript code to access this variable. If you could change that value, then it's not a HttpOnly flagged cookie anymore:)
If you want to send this cookie via javascript, you should send it via the Authorization header for example and write middleware in Java server so that it captures these values from the Authorization header and think of them as JSESSIONID cookie. No more options for you :)
I also had this issue, and i just fixed it right now.
I realized that is you pass option {withCredentials: true} your browser will automatically send all available cookies along with your request. That way you don't have to add the cookies manually, so it's fluent and i thinks it also safer.
Change your code to this and see and check.
Cookies are available when the path is same as your front end.
private heroesUrl = 'http://localhost:8080/hi';
getMessage() :Observable<Message>{
return this.http.get<Message>(this.heroesUrl, {withCredentials: true});
}
I am trying to integrate Microsoft Azure Active directory in my application,
Here's what I have able to achieve so far and where I am stuck -
1.
My URI to request an Authorization code -
https://login.microsoftonline.com/{{tenant-id}}/oauth2/authorize?
response_type=code%20id_token
&scope=openid
&response_mode=query
&redirect_uri=http://localhost:8081/dashboard.html
&client_id={{client-id}}
&nonce={{nonce}}
&site_id={{site_id}}
I have been able Authenticate the user and successfully redirect the authenticated user to the redirect_uri page,
My Front end received 3 things from AD after successful redirection -
a) id_token
b) code
c) session_state
2.
Using these I am able to successfully ake a post call to the Microsoft endpoint, to receive Access tokens, following are the call details -
Endpoint - https://login.microsoftonline.com/{{tenant-id-here}}/oauth2/token
Type - Post
Headers - Content-Type
Body(application/x-www-form-urlencoded) - grant_type, code, client_id, redirect_uri, client_secret, resource
3.
Microsoft endpoint responds with following data -
a) token_type
b) expires_in
c) ext_expires_in
d) expires_on
e) access_token
f) refresh_token
g) id_token
4.
Now as per the OAuth process, my Front end passes the access_token on every API call, this access_token is supposed to be verified by hitting some Microsoft endpoint, which I believe is the following one -
Endpoint - https://graph.microsoft.com/v1.0/me/messages
Type - Get
Header - Authorization
Header value - Bearer {{Access-token}}
Parameters - client_id
Error message -
This request if failing with 404
Can someone help me understand -
1. Am I hitting the correct endpoint to verify the access_token?
2. If yes what a I doing wrong?
3. If no, which is the correct endpoint? and what should be it's request details?
Here are my reference docs -
1. https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-v2-protocols-oauth-code
2. https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-protocols-oauth-code
Tried hitting the following endpoint as well -
Endpoint - login.microsoftonline.com/{{tenant-id}}/oauth2/authorize
Type - Post
Header - Authorization, Content-Type
Header value for Authorization- Bearer {{Access-token}}
Header value for Content-Type- application/x-www-form-urlencoded
Body(application/x-www-form-urlencoded) - client_id
Try specifying the resource parameter.
Even though it is said to be optional, it is included in every sample here: https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-protocols-oauth-code.
So when you retrieve the tokens from https://login.microsoftonline.com/{tenant-id}/oauth2/token, remember to include the resource parameter, and set its value to https://graph.microsoft.com to get tokens to use on Microsoft Graph API.
I can also say that in your screenshot you are not passing the access token in the header. That looks like an authorization code or refresh token. You must pass the access token.
I am trying to retrieve user photo using outlook REST API(https://msdn.microsoft.com/en-us/office/office365/api/photo-rest-operations#UserphotooperationsGetphoto)
I got the access token following (https://msdn.microsoft.com/en-us/library/azure/dn645543.aspx)
but getting this error : any help?
HTTP/1.1 401 Unauthorized [Content-Length: 0, Server: Microsoft-IIS/8.0, request-id: 6925fcab-9021-4059-af4b-4cbf130faea7, X-CalculatedBETarget: CY1PR0401MB1388.namprd04.prod.outlook.com, X-BackEndHttpStatus: 401, Set-Cookie: exchangecookie=87cb2447eae9401c80a96c497dff06a9; expires=Sat, 22-Apr-2017 07:56:53 GMT; path=/; HttpOnly, x-ms-diagnostics: 2000001;reason="The access token is acquired using an authentication method that is too weak to allow access for this application. Presented auth strength was 1, required is 2.";error_category="invalid_token",
code looks something like this:
HttpClient httpclient = HttpClients.createDefault();
final String bearerToken = getBearerToken();
HttpGet request = new HttpGet("https://outlook.office.com/api/v2.0/me/photo/$value");
request.setHeader(javax.ws.rs.core.HttpHeaders.AUTHORIZATION, "Bearer " + bearerToken);
request.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE);
HttpResponse response = httpclient.execute(request);
return IOUtils.toByteArray(response.getEntity().getContent());
According to the error message. Instead of a client_secret in your request body, you need a client_assertion.
For more details, you can reference the blog Building Daemon or Service Apps with Office 365 Mail, Calendar, and Contacts APIs (OAuth2 client credential flow)
According to the API you call "https://outlook.office.com/api/v2.0/me/photo/$value". It seems that you only want to get the photo for the current login user; if so, you can use Authorization Code Grant Flow to get the token which will not require the client certificates.
UPDATE#1:
Can this be done programmatically/API way
As far as I know, the consent need the user's or admin's interactivity.
https://login.windows.net/common/oauth2/authorize?response_type=code&client_id={0}&resource={1}&redirect_uri={2}&prompt={3}
If you are developing a ASP.NET web application, you can reference the sample project O365-WebApp-MultiTenant.
BTW, when calling the API with app-token, you need to specify the user name.
e.g.
https://outlook.office.com/api/v2.0/users('user1#customdomain.onmicrosoft.com')/messages
UPDATE#2:
The 403 code when updating the photo using the app token is expected result.
As we can see from the figure above, updating the user photo requires the delegated permission "User.Read.Write". The app token does not have permission to update user's photo.
I'm in the process of learning how to use HP Quality Center's REST api to query and manipulate data. Unlike REST standard, this API is not completely stateless. It uses cookies to store authentication sessions.
I've tried to implement a very simple test, using the Jersey Client library. I can successfully authenticate my user, by sending my credentials. The API reference claims that this will set a cookie, and I am good to go with further calling the REST api. However, a simple "is-authenticated" call returns a 401, Authentication failed.
I have a feeling that the cookie writing or reading is not working properly, as everything else seems to work as it should. But I haven't been able to find out if or how cookies are set and read, when no browser is involved. So How does cookies work, when calling cookie-setting REST services from java VM? Does it work at all? Where are they stored?
I am using Eclipse Kepler as my IDE, if that matters at all, and a 32-bit java 1.6 JDK and JRE.
Code, and response strings below:
1. Logging in:
Client client = ClientBuilder.newClient();
Response response = client
.target("http://[host]:[port]").path("qcbin/authentication-
point/alm-authenticate")
.request().post(Entity.entity("<alm-authentication>
<user>username</user>
<password>secret</password></alm-authentication>",
MediaType.TEXT_XML_TYPE));
System.out.println(response.toString());
Output:
InboundJaxrsResponse{ClientResponse{method=POST,
uri=http://[host]:[port]/qcbin/authentication-point/alm-authenticate,
status=200, reason=OK}}
API Return description:
One of:
HTTP code 200 and sets the LWSSO cookie (LWSSO_COOKIE_KEY).
HTTP code 401 for non-authenticated request. Sends header
WWW-Authenticate: ALMAUTH
2. Verifying Logged in:
response = client.target("http://[host]:[port]")
.path("qcbin/rest/is-authenticated")
.request().get();
System.out.println(response.toString());
Output:
InboundJaxrsResponse{ClientResponse{method=GET,
uri=http://[host]:[port]/rest/is-authenticated, status=401,
reason=Authentication failed. Browser based integrations - to login append
'?login-form-required=y to the url you tried to access.}}
PS: adding the ?login-form-required=y to the URL, will bring up a log-in window when called in a browser, but not here. Appending the line to the URL actually still gives the same error message, and suggestion to append it again. Also, when called in a browser, the is-authenticated returns a 200, success, even without the login-form.
When you log in, you're getting a cookie which is a name plus a value.
The REST server expects you to pass this in the request header with every request you make.
Look into the object which you get for client.request(); there should be a way to specify additional headers to send to the server. The header name must be Cookie and the header value must be name=value.
So if the server responds with a cookie called sessionID with the value 1234, then you need something like:
client.request().header("Cookie", "sessionID=1234")
Related:
http://en.wikipedia.org/wiki/HTTP_cookie
I trying to send a payment with my test application. Im using the paypal java sdk package.
Im not receiving my access token. Im receiving only the bearer token,
Bearer WesirDWp61YcTr8N8XWZHnPk7tCch.ZgcMvLfyp-FRA : appId :
APP-80W284485P519543T
Thus when I try to send a payment Im getting and 401 authorization error because of no access token. The first time I sent the request it returned the access token but every subsequent attempt brings this error:
Java exception "com.paypal.core.rest.PayPalRESTException: Error code : 401
with response : Server returned HTTP resp" when calling method "create" with
signature "(Ljava.lang.String;)Lcom.paypal.api.payments.Payment;" in class
"com.paypal.api.payments.Payment".
I do not understand what is happening here . Am I completely missing the boat here?
Thank You for any response.
Hit this URL with POST Request on Postman.
POST https://api.sandbox.paypal.com/v1/oauth2/token
On Authorization choose basic auth and enter the username as a clientID and password as a ClientSecret.
In Header set Content-Type: application/x-www-form-urlencoded
In Body seelect x-www-form-urlencoded and write grant_type: client_credentials
after that send request you will get the access_token
The bearer token is the access token, more specifically it is the type of access token returned. As per the REST API Reference (which is what the java sdk calls), the call to the oauth end point returns:
{
"scope": "https://api.paypal.com/v1/payments/.* https://api.paypal.com/v1/vault/credit-card https://api.paypal.com/v1/vault/credit-card/.*",
"access_token": "EEwJ6tF9x5WCIZDYzyZGaz6Khbw7raYRIBV_WxVvgmsG",
"token_type": "Bearer",
"app_id": "APP-6XR95014SS315863X",
"expires_in": 28800
}
The SDK combines the two fields and returns them as the "Bearer token".
This bearer token is all you need to access the REST APIs (with some restrictions based on the permissions/scopes requested and how the bearer token was requested, however that is dependent on creation call). Pass the bearer token in the authorization header:
"Authorization: Bearer EEwJ6tF9x5WCIZDYzyZGaz6Khbw7raYRIBV_WxVvgmsG"