Unable to see cookie in response from server in chrome - google-chrome

Same as Why does Chrome ignore Set-Cookie header? but I have provided code for the frameworks I am using.
Here is my original text, I put it as an answer to above (not really an answer but it did provide some code as was requested, but the sysop tells me as it is not an answer I should raise the question again. So here it is...
I have been stuck on this for too long. All works fine in Postman, Firefox, etc, etc, but Chrome stubbornly refuses to accept the Set-Cookie header.
My server (Spring Zuul Proxy)
#Bean
public CorsFilter corsFilter() {
logger.info("=================> corsFilter intialization.");
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
final CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.setAllowedOrigins(Collections.singletonList("http://neptune.local.mydoman.org:4200"));
config.setAllowedHeaders(Collections.singletonList("*"));
config.setAllowedMethods(Arrays.stream(HttpMethod.values()).map(HttpMethod::name).collect(Collectors.toList()));
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
Pretty open, but not worried about that, I will tighten up once I have it working.
I want to store the refresh_token in a HTTP Only cookie, I have relaxed that for testing to see if the cookie is set.
My PostFilter to set the cookie before response is sent.
#Component
public class CustomPostZuulFilter extends ZuulFilter {
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private final ObjectMapper mapper = new ObjectMapper();
// Default is 30 days
#Value("${oauth.http.cookie.maxAge:2592000}")
private int cookieMaxAge;
#Override
public Object run() {
final RequestContext ctx = RequestContext.getCurrentContext();
logger.info("PostZuulFilter called: " + ctx.getRequest().getRequestURI());
final String requestURI = ctx.getRequest().getRequestURI();
final String requestMethod = ctx.getRequest().getMethod();
try {
final InputStream is = ctx.getResponseDataStream();
String responseBody = IOUtils.toString(is, "UTF-8");
if (responseBody.contains("refresh_token")) {
final Map<String, Object> responseMap =
mapper.readValue(responseBody,
new TypeReference<Map<String, Object>>() {
});
final String refreshToken = responseMap.get("refresh_token").toString();
logger.info("Decoding refresh token from response.");
decodeJwtToken(refreshToken);
responseMap.remove("refresh_token");
responseBody = mapper.writeValueAsString(responseMap);
final Cookie cookie = new Cookie("refreshToken", refreshToken);
// cookie.setHttpOnly(true);
// cookie.setSecure(true);
cookie.setPath(ctx.getRequest().getContextPath() + "/oauth/token");
cookie.setMaxAge(cookieMaxAge); // 30 days
ctx.getResponse().addCookie(cookie);
logger.info("PostZuulFilter refresh token now stored in HTTP ONLY cookie:");
logger.info(refreshToken);
}
if (requestURI.contains("oauth/token") && requestMethod.equals("DELETE")) {
final Cookie cookie = new Cookie("refreshToken", "");
cookie.setMaxAge(0);
cookie.setPath(ctx.getRequest().getContextPath() + "/oauth/token");
ctx.getResponse().addCookie(cookie);
}
ctx.setResponseBody(responseBody);
} catch (final IOException e) {
logger.error("Error occured in zuul post filter", e);
}
return null;
}
#Override
public boolean shouldFilter() {
return true;
}
#Override
public int filterOrder() {
return 10;
}
#Override
public String filterType() {
return "post";
}
private String decodeJwtToken(String jwtToken) {
logger.info("------------ Decode JWT ------------");
String[] split_string = jwtToken.split("\\.");
String base64EncodedHeader = split_string[0];
String base64EncodedBody = split_string[1];
String base64EncodedSignature = split_string[2];
logger.info("~~~~~~~~~ JWT Header ~~~~~~~");
Base64 base64Url = new Base64(true);
String header = new String(base64Url.decode(base64EncodedHeader));
System.out.println("JWT Header : " + header);
logger.info("~~~~~~~~~ JWT Body ~~~~~~~");
String body = new String(base64Url.decode(base64EncodedBody));
logger.info("JWT Body : "+body);
return "";
}
}
And finally my Angular Service request.
public obtainAccessToken(params: URLSearchParams): Observable<string> {
console.log('obtainAccessToken');
console.log('Getting access token from ', appConfig.tokenServerUrl);
console.log('Using params: ');
console.dir(params.toString());
// Now fire the request
this.http.post(
'http://neptune.local.domain.org:8084/oauth/token',
params.toString(), {
headers: new HttpHeaders({
'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8'}),
withCredentials: true,
observe: 'response'
})
.pipe(map((response) => {
// Try and find the Set-Cookie header! (Good luck)
console.log(response);
console.log('response headers',response.headers.keys());
const respKeySet = response.headers.keys();
for( let x = 0; x < respKeySet.length; x++ ) {
console.log('Key: %s, Value: %s',
respKeySet[x],
response.headers.get(respKeySet[x]));
}
}));
}
My server and my client are running on the same workstation, I have set the FQD name.
So Client is running on.
http://neptune.local.mydomain.org:4200
My Server is running on.
http://neptune.local.mydomain.org:8084
I never get the Set-Cookie in Chrome???
Anyone know why?
Erm, HELP....

The code in my question is actually working.
The Angular service request never displays the Set-Cookie header.
But....
When checking again after numerous changes and stops/restarts I fired another request, still nothing printed out to console. Then I checked the Google Chrome DevTools network tab for the request I sent and hey presto, its there.
Yaay!!!

Related

Xamarin.Android - How to get JSON from website

I want to get JSON data from Site
Nothing shows up about it and Xamarin and I tried these 3 from youtube and it didn't work for me
public void ValidateNumber()
{
string URL = "http://android-householdinventory-api.epizy.com/ValidateNumber.php?";
WebClient client = new WebClient();
Uri uri = new Uri(URL + "number=10");
client.DownloadDataAsync(uri);
client.DownloadDataCompleted += Client_DownloadDataCompleted;
}
private void Client_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
{
//throw new NotImplementedException();
string json = Encoding.UTF8.GetString(e.Result);
System.Console.WriteLine(json);
}
public async void Validationv2()
{
using (var client = new HttpClient())
{
var uri = "http://android-householdinventory-api.epizy.com/ValidateNumber.php?number=100";
var Result = await client.GetStringAsync(uri);
System.Console.WriteLine(Result);
}
}
public void Validationv3()
{
WebClient wclient = new WebClient();
string a = wclient.DownloadString("http://android-householdinventory-api.epizy.com/ValidateNumber.php?number=100");
System.Console.WriteLine(a);
}
All Results to this:
<html><body><script type="text/javascript" src="/aes.js" ></script><script>function toNumbers(d){var e=[];d.replace(/(..)/g,function(d){e.push(parseInt(d,16))});return e}function toHex(){for(var d=[],d=1==arguments.length&&arguments[0].constructor==Array?arguments[0]:arguments,e="",f=0;f<d.length;f++)e+=(16>d[f]?"0":"")+d[f].toString(16);return e.toLowerCase()}var a=toNumbers("f655ba9d09a112d4968c63579db590b4"),b=toNumbers("98344c2eee86c3994890592585b49f80"),c=toNumbers("304feeb55638873348a9f20961a94049");document.cookie="__test="+toHex(slowAES.decrypt(c,2,a,b))+"; expires=Thu, 31-Dec-37 23:55:55 GMT; path=/"; location.href="http://android-householdinventory-api.epizy.com/ValidateNumber.php?number=10&i=1";</script><noscript>This site requires Javascript to work, please enable Javascript in your browser or use a browser with Javascript support</noscript></body></html>
How to fix this?
I'm new to c# and Xamarin
Your API server is returning HTML response for this "http://android-householdinventory-api.epizy.com/ValidateNumber.php?number=100" end point that's why it is showing HTML in response. You will have to correct the api response on server side.
try this! working example
private async void btn_Login_Clicked(object sender, EventArgs e)
{
List<LoginDetails> UserDetails = await _services.LoginAsync(string username, string password)
}
public async Task<List<LoginDetails>> LoginAsync(string username, string password)
{
List<LoginDetails> UserList;
using (var client = new HttpClient())
{
LoginDetails Ld = new LoginDetails();
Ld.UserName = username;
Ld.Password = password;
string url = "";
//HttpClient client = new HttpClient();
string jsonData = JsonConvert.SerializeObject(Ld);
StringContent content = new StringContent(jsonData, Encoding.UTF8, "application/json");
HttpResponseMessage response = await client.PostAsync(url, content);
string result = await response.Content.ReadAsStringAsync();
UserList = JsonConvert.DeserializeObject<List<LoginDetails>>(result);
//loginDetails = new ObservableCollection<LoginDetails>(UserList);
}
return UserList;
}
I was hosting on InfinityFree and it has aes.js so it may be causing that result.
This helped me in getting the solution
Setting Authorization Header of HttpClient
ByetHost server passing html values "Checking your browser" with JSON String
[I added this before client.GetAsync]
client.DefaultRequestHeaders.Add("Cookie", "__test=<COOKIE_CONTENT>; expires=<COOKIE_EXPIRATION>; path=/");

How do I send a HTTP request using OAUTH2 in Android?

I am trying to retrieve the data from my account by connecting to the Fitbit API. I have my app returning the Access Token I need to make the HTTP Request that returns the JSON but anything that I try, it returns an error. I have two Activities - MainActivity.java and TestActivity.java
In MainActivity.java I am simply opening a Chrome Custom Tab to direct the user to the Fitbit Authentication(Login) page. Once the user enters their details they are redirected back to the TestActivity.java as per the Fitbit API documentation. I am then printing the Acess Token which proves to me that it is connecting to the API.
What I need to do it make an HTTP request to returns the sleep data in JSON format. I know how to do it in Java but I am unsure how to do it in Android using the AsyncTask way. Any help is appreciated!
public class TestActivity extends AppCompatActivity {
String string;
String token;
#Override
protected void onNewIntent(Intent intent) {
string = intent.getDataString();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
onNewIntent(getIntent());
//Toast.makeText(TestActivity.this, string , Toast.LENGTH_LONG).show();
Log.e("TAG", string);
Log.e("TAG", string.substring(string.indexOf("&access_token")+14));
token = string.substring(string.indexOf("&access_token")+14);
Context context = getApplicationContext();
Toast toast = Toast.makeText(context,"Access Token: "+ token,Toast.LENGTH_LONG );
Log.i("TAG", "Access Token: "+ token);
new JSONTask().execute("https://api.fitbit.com/1.2/user/-/sleep/date/2018-01-30.json");
}
public class JSONTask extends AsyncTask<String,String,String>
{
#Override
protected String doInBackground(String... params) {
HttpURLConnection connection = null;
BufferedReader reader = null;
try
{
URL url = new URL(params[0]);
connection.setRequestMethod("GET");
connection.setRequestProperty("Authorization", "Bearer " + token);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
InputStream stream = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(stream));
StringBuffer buffer = new StringBuffer();
String line = "";
while((line = reader.readLine()) !=null)
{
buffer.append(line);
}
return buffer.toString();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String s)
{
super.onPostExecute(s);
Log.i("TAG", s);
}
}
I ended up having a breakthrough with this question. I figured out that I was extracting the Access Token incorrectly. So, instead of doing the following:
token = string.substring(string.indexOf("&access_token")+14);
I instead had to use this:
token = string.substring(string.indexOf("&access_token")+36,308);
The App was then able to make the necessary HTTP request to the Fitbit API which returned the JSON data that I needed.
One order of codes should be changed for preventing FC.
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Authorization", "Bearer " + token);

How to run JUnit testing on Firebase Java with authentication?

I am currently using Firebase Authentication in my mobile app. The back end is a Spring boot application. The REST APIs on the back end relies on a token generated from Firebase Authentication to retrieve the Firebase UID (verifyIDToken method) of a user to perform further functions.
Currently, I notice that in Firebase Java API (server-based), there is no way of generating a token for a user, thus there is no easy way for me to do JUnit testing on the server that relies on user authentication. Anyone has clues on how to do so?
This is the sample code that does not work:
#RequestMapping(value = "/api/subscribeChannel/{channelid}", method = RequestMethod.GET, produces = "application/json")
public DeferredResult<Object> subscribeChannel(#PathVariable Long channelid,#RequestHeader(value=FIREBASETOKEN, required = true) String idToken) {
DeferredResult<Object> result = new DeferredResult<Object>(DEFERREDTIMEOUT);
// test it out with a locally generated token
idToken = FirebaseAuth.getInstance().createCustomToken("valid Uid");
Task<FirebaseToken> task = FirebaseAuth.getInstance().verifyIdToken(idToken)
.addOnSuccessListener(new OnSuccessListener<FirebaseToken>() {
#Override
public void onSuccess(FirebaseToken decodedToken) {
String uid = decodedToken.getUid();
logger.info("Subscribe channel on success");
// do something
ret.setStatus("success");
ret.setMessage("channel id " + channelid + " subscribed");
result.setResult(ret);
} else {
result.setErrorResult(retStatus.getMessage());
}
}
}) .addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(Exception arg0) {
Exception te = new TokenNotFoundException(idToken);
logger.error("Token Not Found for " + idToken);
result.setErrorResult(te);
}
});
return result;
}
The custom token you get is different from the ID token that you use to log on. To get an id token from a custom token, do this:
private static final String ID_TOOLKIT_URL =
"https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyCustomToken";
private static final JsonFactory jsonFactory = Utils.getDefaultJsonFactory();
private static final HttpTransport transport = Utils.getDefaultTransport();
private static final String FIREBASE_API_KEY = "<your api key here>";
private String signInWithCustomToken(String customToken) throws IOException {
GenericUrl url = new GenericUrl(ID_TOOLKIT_URL + "?key="
+ FIREBASE_API_KEY);
Map<String, Object> content = ImmutableMap.<String, Object>of(
"token", customToken, "returnSecureToken", true);
HttpRequest request = transport.createRequestFactory().buildPostRequest(url,
new JsonHttpContent(jsonFactory, content));
request.setParser(new JsonObjectParser(jsonFactory));
com.google.api.client.http.HttpResponse response = request.execute();
try {
GenericJson json = response.parseAs(GenericJson.class);
return json.get("idToken").toString();
} finally {
response.disconnect();
}
}
The Java API to generate custom tokens is documented under Create custom tokens using the Firebase SDK.
From there:
String uid = "some-uid";
String customToken = FirebaseAuth.getInstance().createCustomToken(uid);

Detecting when a web service post has occured

I just wrote a simple windows 8 form that post to web service api. It works fine. But my challenge is been able to determine when the post operation was a success and a failure. I dont know how to return a value cos aysnc Task is not allowing a return type.
//This class does the post to web service
public class B2cMobileuserService : IB2cMobileuserService
{
private string RegisterUserUrl = RestfulUrl.RegisterMobileUser;
private readonly HttpClient _client = new HttpClient();
public async Task RegisterMobileUser(B2cMobileuserView user)
{
var jsonString = Serialize(user);
var content = new StringContent(jsonString, Encoding.UTF8, "application/json");
var result = await _client.PostAsync(RegisterUserUrl, content);
}
}
//This class calls the one above
public class WebserviceProcessor
{
//declaring all the service objects that would be used
IB2cMobileuserService mobileuserService = null;
public WebserviceProcessor() {
mobileuserService = new B2cMobileuserService();
}
//This method is going to post values to the web serever
public async void RegisterUser(B2cMobileuserView mobileuser) {
mobileuserService.RegisterMobileUser(mobileuser);
}
}
//Then the code below is from my .xaml user interface that calls the class that sends to webservice
private void Button_Click(object sender, RoutedEventArgs e)
{
B2cMobileuserView user = new B2cMobileuserView();
user.Name = name.Text;
user.Email = email.Text;
user.PhoneType = "Windows Mobile";
user.BrowserType = "None";
user.CountryName = "Nigeria";
user.UserPhoneID = phone.Text;
Serviceprocessor.RegisterUser(user);
progressBar.Visibility = Visibility.Visible;
}
Please I dont know how to return a value cos when I try I get the error that says async method must be void.
I need to set a way to know when the post was a success based on the return value from the web service.
To ensure the POST was successful, call HttpResponseMessage.EnsureSuccessStatusCode:
public async Task RegisterMobileUser(B2cMobileuserView user)
{
var jsonString = Serialize(user);
var content = new StringContent(jsonString, Encoding.UTF8, "application/json");
var result = await _client.PostAsync(RegisterUserUrl, content);
result.EnsureSuccessStatusCode();
}
If you want to return a value, use a Task<T> return type instead of Task.
On a side note, avoid async void; use async Task instead of async void unless the compiler forces you to write async void:
//This method is going to post values to the web serever
public Task RegisterUser(B2cMobileuserView mobileuser) {
return mobileuserService.RegisterMobileUser(mobileuser);
}
Also, you should name your asynchronous methods ending in *Async:
//This method is going to post values to the web serever
public Task RegisterUserAsync(B2cMobileuserView mobileuser) {
return mobileuserService.RegisterMobileUserAsync(mobileuser);
}
You may find my async intro and MSDN article on async best practices helpful.

How do I read the basic authorization in a ASP.Net MVC4 api GET request

I have a phone app that trys to GET data from my web api using RestSharp
private void ButtonTestTap(object sender, EventArgs e)
{
var client = new RestClient
{
CookieContainer = new CookieContainer(),
BaseUrl = "http://localhost:21688/api/game",
Authenticator = new HttpBasicAuthenticator("muhcow", "123456")
};
RestRequest request = new RestRequest(Method.GET);
request.AddParameter("id", 5);
//request.AddBody(5);
client.GetAsync<LoginResult>(request, (response, ds) =>
{
System.Diagnostics.Debug.WriteLine(response.StatusDescription);
System.Diagnostics.Debug.WriteLine(response.Data);
System.Diagnostics.Debug.WriteLine(response.Content);
});
}
And then want to read the Authenticator = new HttpBasicAuthenticator("muhcow", "123456") when my api server recieves this GET request so I can verify the user, but I am not sure how to read the data.
I have this
public class GameController : ApiController
{
// GET /api/game/5
public string Get(int id)
{
var sdf2 = ControllerContext.Request.Headers.Authorization.Parameter;
//return LoginManager.VerifyLogin(loginData);
return "Some data";
}
But sdf2 just has a wierd value "bXVoY293OjEyMzQ1Ng=="
That header is base64-encoded. Apply Convert.FromBase64String() to it and you'll see the contents.
Authorization.Parameter is base64 encoded. You can look at an example of how to decode it here http://arcanecode.com/2007/03/21/encoding-strings-to-base64-in-c/
System.Text.Encoding.UTF8.GetString (Convert.FromBase64String (this.ControllerContext
.Request .Headers.Authorization.Parameter ))
the result is
"muhcow", "123456"