I am working on Java application . Front end would be Angular2 .
If I try to open my application home page( index.html is configured in web.xml as default page ) . Access URL should be http://localhost:8080/MyWebApp .
Then I have taken into an standard organization's login page for authentication. If authentication succes , HTTP Authorization token will be set in the request header and finally control comes to display my application home page.
If I use jsp, I can get request header as,
String authHeader = request.getHeader("authorization");
out.println("<h2>HTTP Authorization header:</h2>");
if (authHeader == null) {
out.print("No authorization header");
} else {
out.print("<textarea readonly id='authHeader' rows=\"5\" cols=\"80\">" + authHeader + "</textarea>");
}
But we are using html as front end, because of angular 2 .
So for my scenario, how I can I get the request header and token.
Please don't hesitate to edit my question, if it is not clear.
You can't get a value of a header from client-side JavaScript. The only exceptions are the User-Agent and Referrer headers, because the browser provides the values in the document and navigator objects.
You said you are working on a Java application with an Angular 2 front end and some other application provides a token (might be useful to specify if this is something standard, e.g. OAuth2). I will assume that it is a custom token. I believe you also meant you have some server side component, a servlet.
What you can do is to implement the authentication using the servlets (or even JSPs) and then redirect back to the Angular 2 front end application, passing the token in the URL as a query parameter. URL is easy to read in Angular 2. However this is not very secure, even if you use something like JWT. As an alternative to URL, you can use the Set-Cookie header and then read the cookie from Angular.
What would be almost secure would be to authenticate the user using the server side (servlet or even JSP). Then create a one-time token which is passed in the URL as a query parameter when redirecting to your HTML page. Then use the one-time token in a call to the server again to retrieve the real authentication token using a proper REST call from Angular 2 with request and response.
Depends on how much control you have and what kind of authentication the auth application uses, you might want to take a look at the OAuth2. It deals with plenty of different authentication scenarios. Specifically the OAuth2 implicit grant flow is used to authenticate users from client-side only applications. Even if you can't use that, it will give you some ideas.
When you are using a server-side authorization, your server put headers with authorization to your HTML pages. But also you can put this tokens to your page response by meta tags at server side. And then access to meta tags by js.
<meta name="_csrf" content="${_csrf.token}"/>
<meta name="_csrf_header" content="${_csrf.headerName}"/>
Meta tags are similar to response headers and can complete or override response headers.
Read this post please Spring Security CSRF Token not working with AJAX call & form submit in same JSP
You can handle this at server side(JSP's expressions work on server side), create a handler method on server where you can check header and then redirect to your Angular App.
I think we can use HTTP HEAD method as JQUERY AJAX request in your HTML page .
https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol
The HEAD method asks for a response identical to that of a GET request, but without the response body. This is useful for retrieving meta-information written in response headers, without having to transport the entire content.
ajaxRequest = $.ajax({
type: "HEAD",
async: true,
url: 'index.jsp',
success: function(message){
var headerValue =ajaxRequest.getResponseHeader('Content-Length')]);
}
});
There are various way to solve this issue as I faced it a lot before and what I prefer is;
When authentication is completed in login page and a token generates I store it into HTML storage, make be in localStorage.
The main point you should understand that your views should not be accessed directly and there has to be a authentication (or may be a authorisation) step(s) before accessing the page(view).
So what you can do is set a URI for accessing any page, consider that is;
http://host/appname/pageName
And when you connect with this URI via ajax call add the token that is stored in localStorage in headers. And check all authentication and authorisation works and if success return the view(as the pageName suggested in the URI), else return the login view.
If i understand you correctly,
Angularjs is a client side framework and is intended to run inside a browser without any intervention of server by reducing its load by serving the application logic
All operations that need to be performed by angular will only be initiated at client side by the browser after loading the HTML and javascript.
The scope of angular is only limited to that area any way it is not a disadvantage it is the actual intention of client side frameworks.
Regarding request response headers you can only have access to headers of AJAX request
Following are the solutions to these problems:-
If you are using tomcat or any servelet container in order to serve the application or hosting angular code you can use JSP insted of HTML,since JSP is processed to html by the servelet container before passing it to client side.I think this solution will work in your case based on my inference form your question
Otherwise configure servelet that process the success and failure handlers from the authentication server and from angular you need to poll the servelet for getting the request header value.
Related
My WebAPI is, just that, an API backend for my UI to consume. In fact, I will have perhaps 10's of WebAPI services that my UI will use.
I'm having difficulty understanding what I need to consider in terms of security.
My APIs are secured using Bearer tokens, and allow https only. I have CORS set up and they only allow the origin https://my-front.end This all works great.
However.. how can I protect against C/XSRF and replay attacks on a WebAPI? Do I even need to?
Setting up anti-CSRF is rather painless with an ASP.NET MVC project, but how can you do it on a WebAPI one, from what I understand it relies on sending information, generated on the server, to the client to send along in the body of the request and through another channel (e.g. cookie or header). I read that you can protect against replay attacks by using a nonce (e.g. timestamp and random number) -- some how -- but can't find any implementation examples.
Is there anything else I need to consider?
Edit: front end uses vue.js, but we have a very competent JS programmer so any front-end implementations won't be a problem. It's just a matter of finding out what needs to be done!
May also be worth noting, for sake of obviousness, WebAPIs and FrontEnd run on different servers, so these are all, effectively, cross origin calls.
OK so. First up, you will need to be sending the XSRF token in a header. To do this you need to go to your ConfigureServices method and setup the AntiForgery service to expect this header.
public void ConfigureServices(IServiceCollection services)
{
services.AddAntiforgery(x => x.HeaderName = "X-XSRF-TOKEN");
services.AddMvc();
}
Next you need to generate the token. Because the front end and API are different services, you will need to work out when you do this. You could do it when you login for example, or you could have a dedicated endpoint doing this but the end result is the same.
You can either return the token value in a header or cookie it's up to you. In my example I've used a Cookie which I'll explain later but you can use a header if you like.
public class HomeController : Controller
{
private readonly IAntiforgery _antiForgeryService;
public HomeController(IAntiforgery antiForgeryService)
{
_antiForgeryService = antiForgeryService;
}
public IActionResult GetToken()
{
var token = _antiForgeryService.GetTokens(HttpContext).RequestToken;
HttpContext.Response.Cookies.Append("XSRF-TOKEN", token, new CookieOptions { HttpOnly = false });
return new StatusCodeResult(StatusCodes.Status200OK);
}
}
The IAntiforgery service should already be able to be used (It's part of the "AddMVC" call you will be using already in .net core services).
OK, so now we have returned a cookie with a token value. Now we just need to be able to send it back.
Here is some jQuery doing the legwork
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/js-cookie/2.1.4/js.cookie.min.js"></script>
<script type="text/javascript">
var token = Cookies.get("XSRF-TOKEN");
$.ajax({
url: "/",
contentType: "application/json",
type: "POST",
headers: {
"X-XSRF-TOKEN": token
}
});
</script>
Now something to note is that AngularJS automatically does this. When $http is used, it goes and looks for a cookie named "XSRF-TOKEN", and it will then send it as a header automatically. Because you are using Vue you will basically be doing this anyway but a bit more of a manual process.
Also important to note, DO NOT set this up to expect the cookie back as the CSRF token. Otherwise you've defeated the entire purpose of CSRF anyway.
Then you can go ahead and decorate your actions/controllers with the AntiForgery attribute.
[AutoValidateAntiforgeryToken]
public class HomeController : Controller
{
In conclusion what it basically boils down to :
Setup .net Core AntiForgery to expect a header value to use for the CSRF token
Have an endpoint that will manually generate a token for you to use and return it as a cookie/header
Have your front end read this value and store it for subsequent requests
On subsequent requests send the token value as a header (Not a cookie)
Mostly taken from here : http://dotnetcoretutorials.com/2017/05/18/csrf-tokens-angularjsjquery-asp-net-core/
We are working on application, where my friend is working on server side (spring) and he created REST api, and I'm creating client with angularJS. REST and client webpage are on different domains, so I had to faced Same-origin policy - I handled this with php proxy and everything works fine. Until yesterday - now we had authentication service (spring-security) and I have no idea how to login into REST. I can login when I simple write service adress into browser, but I cant get response I need when calling from JS.
When I'm sending simple get request, in response I'm getting HTML code with login page. I putted <form> to login on my page (taken from response, so it's exacly the same as on '/login' page, I just added full action adress), but after send data I'm getting error page with this message:
HTTP Status 403 - Invalid CSRF Token 'blah-blah-many-numbers-and-letters' was found on the request parameter '_csrf' or header 'X-CSRF-TOKEN'.
I'm not changing this CSRF token, so perhaps I don't know the proper way to handle this (now it's sending as paramaeter in POST from form - _csrf is hidden input with value attribute given by server).
So after this too long introduction, my question is: how to login into REST service (through spring-security) from angularJS controller? What is wrong in my way of doing this? (something has to be wrong, because it's not working ;)).
(Sorry for my english mistakes, I'm affraid there are many of them)
Angular have built-in support for CSRF but it use another name for CSRF Token.
If you already have CSRF Token repository in spring webservice, what have you to do is to change CSRF Token header name to XSRF-TOKEN.
You will find whole instruction how to solve your problem on https://spring.io/blog/2015/01/12/the-login-page-angular-js-and-spring-security-part-ii.
You can use Stateless authentication using server signed token i.e.JSON web token(JWT) for securing REST API's and using angularjs for client side implementation.
Please find the below link as reference for implementing the same:
http://blog.jdriven.com/2014/10/stateless-spring-security-part-1-stateless-csrf-protection/
Github:https://github.com/Robbert1/boot-stateless-auth
You need to have custom implementation of class AbstractAuthenticationProcessingFilter to avoid html response when you login into the Rest API.The blog and github reference will guide you in implementating the same.
I am currently integrating Stripe Connect with an Ember.js 1.7.0-beta.4 application (which supports query params). Per Stripe documentation, I need to receive a GET Redirect from Stripe in my Ember.js application, and use the query params to make a final POST request.
So far, I've captured the query params and am attempting to make an AJAX POST from the same controller, but the AJAX POST returns an error because apparently Stripe's API no longer supports CORS - despite a 2-year-old Stripe blog entry saying otherwise:
XMLHttpRequest cannot load https://connect.stripe.com/oauth/token. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin is therefore not allowed access.
The current Stripe docs say to use JSONP, noting in that same blog post that "since JSONP only supports GET requests, but our API uses a variety of request methods, we had to implement HTTP method override support with a _method query parameter."
Unfortunately, I don't know how to integrate the JSONP approach into the Ember.js application.
Stripe's docs instruct me to "Add this script tag to your page to get started with Stripe.js."
<script type="text/javascript" src="https://js.stripe.com/v2/"></script>
Do I just paste this verbatim into a Handlebars.js template? Then how do I make the required POST request with query params? And where?
Bottom Line: How do I integrate Stripe's JSON approach to enable Stripe Connect in my Ember.js application?
I haven't tested it with stripe but i'll break apart your question into 3 parts and try to answer each part.
1) Where to put the script tag?
the script tag would go in the header
<script type="text/javascript" src="https://js.stripe.com/v2/"></script>
2) How to make a JSONP request?
You would make a reqular request using $.getJSON all you need to do is make sure that the contains ?callback=? see: http://api.jquery.com/jquery.getjson/#jsonp
3) How to do a GET request using _method to override the method.
You would do something like
$.getJSON('http://connect.stripe.com/whatever-the-correct-url-is?callback=?', {
_method: 'POST'
})
If you made a request like that the server should process it as a POST
To Tie it all together you should need to do something like in step 3 but also add in the rest of the params that stripe requires.
You can do it all server side, there is no need to work it into Ember.
The workflow is you redirect a user to the stripe server with your client id. It redirects the user back to an endpoint on your server with a code. You make a call to stripe with that code to obtain a token. After (or during if you want to be cool and async) you redirect the user back to the appropriate ember endpoint. The Stripe js file isn't necessary at all for this portion.
https://stripe.com/docs/connect/oauth#token-request
I have a service url that includes username password like this: http://service.com/token?username=asd&password=123 But I can not send a request from javascript, because username and password is appearing from browser source code. So I created a Proxy page on server that sends request to service and gets token like this: http://mydomain.com/Token/GetToken
I created an index page http://mydomain.com/index.html and javascript code sends request to Proxy page and gets token.
But somebody write a server page that sended request to my Proxy page (http://mydomain.com/Token/GetToken). And can get token.
I want to that only my rendered pages should send request to my Proxy page. Is this possible?
I am using .net mvc Project.
The general approach is to use an existing authentication framework to protect http://mydomain.com/Token/GetToken.
If you're using a PHP backend I suggest uLogin
I know this is a long shot, but I figured I'd ask the question anyway.
I have an HTTPS page and am dynamically creating a form. I want to POST the form to an HTTP page. Is this possible without the browser popping up a warning? When I do this on IE8, I get the following message:
Do you want to view only the webpage content that was delivered securely?
Essentially, I'm asking about the inverse of question 1554237.
Sadly, I know of absolutely no way to not get warned when posting from HTTPS to HTTP. If you serve the form securely, the browser expects to submit the data securely as well. It would surprise the user if anything else was possible.
Nope, can't be done. Our good friend IE will always pop up that warning.
There is a way to do this if you write a back-end service of your own. So lets say you want to post an HTTP request to s1 using your front-end service fs1.
If you use Spring, you can use an ajax call from fs1 to a 'uri' that is recognized by your spring back-end, say bs1. Now, the service bs1 can make the call to the s1.
Pictorial representation here: http://i.stack.imgur.com/2lTxL.png
code:
$.ajax
({
type: "POST",
uri:/json/<methodName>
data: $('#Form').serialize(),
success: function(response)
{
//handle success here
},
error: function (errorResponse)
{
//handle failure here
}
})
You can solve this by either acting as a proxy for the form destination yourself (i.e. let the form submit to your server which in turn fires a normal HTTP request and returns the response), or to let access the page with the form by HTTP only.
If you don't need to actually redirect to the insecure page, you can provide a web service (authenticated) that fires off the request for you and returns the data.
For example:
From the authenticated page, you call doInsecure.action which you create as a web service over https. doInsecure.action then makes a manual POST request to the insecure page and outputs the response data.
You should be able to do this with the opensource project Forge, but it sounds like overkill. The Forge project provides a JavaScript interface (and XmlHttpRequest wrapper) that can do cross-domain requests. The underlying implementation uses Flash to enable cross-domain (including http <=> https) communication.
http://github.com/digitalbazaar/forge/blob/master/README
So you would load the Forge JavaScript and swf from your server over https and then do a Forge-based XmlHttpRequest over http to do the POST. This would save you from having to do any proxy work on the server, but again, it may be more work than just supporting the POST over https. Also, the assumption here is that there's nothing confidential in the form that is being posted.