Sending cookies with Spring Boot and Graphql - spring-boot

Is it possible to send cookies with graphql? With Rest API it was working fine, for eg. Controller like this:
public AppUser returnCookie(HttpServletResponse response) {
Cookie cookie = new Cookie("cookieName", "cookieValue");
cookie.setMaxAge(7 * 24 * 60 * 60);
cookie.setSecure(true);
cookie.setHttpOnly(true);
response.addCookie(cookie);
return appUserService.login(privateToken);
}
Can I have something similar with graphql?

Related

How to change an additional information of jwt access token

I'm working with Spring Security and use JWT as access token , When a client sends the access token to server I must change an additional information (metadata) of this token and return a new one.
How can I achieve that ?
i try with this code but not working
String authorization = Context.getHeader("Authorization");
if (authorization != null) {
String tokenValue = authorization.replace("Bearer", "").trim();
OAuth2AccessToken accessToken = tokenStore.readAccessToken(tokenValue);
accessToken.getAdditionalInformation().put("activeProfileId", defaultProfileId);
return accessToken.getValue();
}
return null;
You should get your metadata ("claims") from the token, then add them to a new JWT builder that will return a new token. The new JWT must be entered in HttpResponse to forward it to the client. Instead, the client will have to implement an interceptor to retrieve it in a comfortable and transparent way.
You've to get all Additional Information as HashMap and place them in OAuth2Authentication. stackoverflow.com/a/19057480/11951081
In ajax should be:
https://api.jquery.com/category/ajax/global-ajax-event-handlers/
$.ajaxSetup({
beforeSend: function (xhr) {
xhr.setRequestHeader('Authorization', <Jwt>)
},
success:function(event,jqXHR,ajaxOptions,data ){
console.log(ajaxOptions.getResponseHeader('Authorization'))
}
})

Adding the application autehntication to Swagger UI

I have Spring boot app where I integrate JWT authentication.
In order to authenticate, user need to send a POST request to /login with username and password, then he gets a JSON response with {"token": "BEARER SOME_TOKEN" }.
In my swagger UI, when I click "Try it out" and execute a request, the request is being sent without any token.
Question - Is there any way to query a login request and add authorization token to the Swagger UI requests?
In this case we can intercept the tokens and add them to all the requests by using these two interceptors in the index.html when defining SwaggerUIBundle:
const ui = SwaggerUIBundle({
...
responseInterceptor:
function (response) {
if (response.obj.access_token) {
console.log(response.obj.access_token)
const token = response.obj.access_token;
localStorage.setItem("token", token)
}
return response;
},
requestInterceptor:
function (request) {
request.headers.Authorization = "Bearer " + localStorage.getItem("token");
return request;
}
}
The responseInterceptor captures the response and if it contains the field "token" it saves it in local storage.
The requestInterceptor adds the Authorization header on each call you make from swagger-ui using the value from local storage.
This fix is for using v3 of swagger-ui:
<script src="https://unpkg.com/swagger-ui-dist#3.12.1/swagger-ui-standalone-preset.js"></script>
<script src="https://unpkg.com/swagger-ui-dist#3.12.1/swagger-ui-bundle.js"></script>

Enable authenticator manually

Currently my client authenticates request only on case of 401 response:
this.client.authenticator(new okhttp3.Authenticator() {
public Request authenticate(Route route, Response response) throws IOException {
String credentials = authenticator.getCredentials();
if (credentials.equals(response.request().header("Authorization"))) {
throw new TraversonException(401, "Unauthorized", response.request().url().toString());
} else {
defaultHeader("Authorization", credentials);
Request.Builder newRequest = response.request().newBuilder()
.headers(Headers.of(defaultHeaders));
return newRequest.build();
}
});
But I'd like to change this behavior and be able to call it either manually or auto per first call? Is it possible somehow?
If the authentication is predictably required and not related to a proxy, then the solution is to implement an Interceptor instead of Authenticator.
OkHttpClient.Builder clientBuilder = ...;
clientBuilder.networkInterceptors().add(0, myInterceptor);
client = clientBuilder.build();
Example Interceptor https://github.com/yschimke/oksocial/blob/48e0ca53b85e608443eab614829cb0361c79aa47/src/main/java/com/baulsupp/oksocial/uber/UberAuthInterceptor.java
n.b. There is discussion around possible support for this usecase in https://github.com/square/okhttp/pull/2458. One issue with current Authenticator API is that it assumes a Response from the failed (401) request.

google ExchangeCodeForTokenAsync invalid_grant in webapi

i have implemented GoogleAuthorizationCodeFlow scenario from google api client dotnet and tutorial to get token from what my client sent to server as a code. but when i call flow.ExchangeCodeForTokenAsync , I get the following error :
{"Error:\"invalid_grant\", Description:\"\", Uri:\"\""}
I read google authorization invalid_grant and gusclass oauth 2 using google dotnet api client libraries but they didn't help me and. I think it must be very simple but I don't know why it doesn't work.
For client side , I have used Satellizer and this is my server Codes:
public bool PostExchangeAccessToken(GoogleClientAccessCode code)
{
string[] SCOPES = { "email" };
IAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow(new GoogleAuthorizationCodeFlow.Initializer
{
ClientSecrets = new ClientSecrets()
{
ClientSecret = "******",
ClientId = "********.apps.googleusercontent.com"
},
Scopes = SCOPES
});
try
{
TokenResponse token;
token = flow.ExchangeCodeForTokenAsync("*****#gmail.com", Newtonsoft.Json.JsonConvert.SerializeObject(code), "https://localhost:44301/",
CancellationToken.None).Result;
}
catch (Exception ex)
{
throw ex;
}
return true;
}
what is the problem?
On Github I found that I must use the Token from the client and use
GoogleAuthorizationCodeFlow.Initializer()
to create my UserCredential object.
You can check your google developer console settings.(Authorized redirect URIs)
Credentials => OAuth 2.0 client IDs => Your Application Settings => Authorized redirect URIs
You must add url. ("https://localhost:44301/")
My code :
flow.ExchangeCodeForTokenAsync("me", authCode, redirectUri, CancellationToken.None).Result;
Authorized redirect URIs
For use with requests from a web server. This is the path in your application that users are redirected to after they have authenticated with Google. The path will be appended with the authorization code for access. Must have a protocol. Cannot contain URL fragments or relative paths. Cannot be a public IP address.

ALM 12 REST using SpringFramework RestTemplate: "401 QCSession cookie missing"

In ALM 12 we have to explicity call "qcbin/rest/site-session" to get session.
When I GET call "/qcbin/rest/site-session" I receive the following:
"Set-Cookie=[BIGipServerALMAST330P-QC=rd100o00000000000000000000ffff0fe0dd74o8080; path=/, ]""
I extract the cookie as described here:
HP ALM 12 REST not returning QCSession cookie.
Instead of this RestConnector, our project is using RestTemplate from SpringFramework, so I did:
private HashMap getQCSession() throws Exception {
URL url = new URL("https://almxxxx.saas.hp.com/qcbin/rest/site-session?login-form-required=y");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/xml");
conn.setRequestProperty("Accept", "application/xml");
conn.connect();
HashMap cookies = updateCookies(conn);
return cookies;
}
public HashMap updateCookies(HttpURLConnection conn) {
String cookie2 = conn.getHeaderField("Set-Cookie");
int equalIndex = cookie2.indexOf('=');
int semicolonIndex = cookie2.indexOf(';');
String cookieKey = cookie2.substring(0, equalIndex);
String cookieValue = cookie2.substring(equalIndex + 1, semicolonIndex);
HashMap cookies = new HashMap();
cookies.put(cookieKey, cookieValue);
System.out.println(cookies.toString());
return cookies;
}
To send the cookie in the GET call using the RestTemplate I followed the instructions from http://springinpractice.com/2012/04/08/sending-cookies-with-resttemplate/, so I did:
public <U extends Object> ResponseEntity<U> getFromURL(URI url, Class<U> responseBodyClass) throws Exception {
logger.info("GET na URL: {} esperando classe: {} no response", url, responseBodyClass);
HashMap cookie = this.getQCSession();
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.add("Cookie", this.getQCSession().toString());
this.httpEntity = new HttpEntity(null, requestHeaders);
return super.exchange(url, HttpMethod.GET, this.httpEntity, responseBodyClass);
}
The requestHeaders content added to the HttpEntity (SpringFramework) is:
{Cookie=[{BIGipServerALMAST330P-QC=rd100o00000000000000000000ffff0fe0dd74o8080}]}
However I'm still getting "401 QCSession cookie missing".
I already tried to send in the GET call the JSESSIONID, with no success as well.
I appreciate any help.
Any clue?
I ran into this. As of ALM12 you need to create a session also.
I POST some XML or JSON to here "/authentication-point/alm-authenticate" to authenticate
Then collect the Set-Cookie header
I then POST to "/rest/site-session" with the cookie from the previous response.
I collect the session cookies from that response to use in my subsequent requests.
Hope that helps
I don't know, if it can help you but you are sending it with query param for UI authentication.
"POST .../rest/site-session?login-form-required=y"
I would suggest to POST it without query param
"POST .../rest/site-session"
Also the order of actions you should do before asking for QCSession token is:
1.Check whether you are authenticated
"GET .../rest/is-authenticated"
2.If not you'll get reference where to authenticate: WWW-Authenticate: LWSSO realm=".../authentication-point"
3.Send basic auth header to authentication point with added alm-authenticate at the end. Which returns you LWSSO_COOKIE_KEY.
"POST .../authentication-point/alm-authenticate"
Authentication: Basic BASE64{username:password}
4.Then you'll need to POST that LWSSO_COOKIE_KEY to site-session and ALM will return you QCSession key.
"POST .../rest/site-session"
"Cookie: LWSSO_COOKIE_KEY={cookie}; Path=/"
Hopefully I was able to help you.
If you still have problems, feel free to contact me.

Resources