New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(security): Automatic XSRF handling. #8898

Merged
merged 1 commit into from May 31, 2016

Conversation

Projects
None yet
9 participants
@mprobst
Contributor

mprobst commented May 28, 2016

What kind of change does this PR introduce? (Bug fix, feature, docs update, ...)

  • Feature

Does this PR introduce a breaking change?

  • Yes
  • No

Automatically recognize XSRF protection cookies, and set a corresponding XSRF
header. Allows applications to configure the cookie names, or if needed,
completely override the XSRF request configuration by binding their own
XSRFHandler implementation.

Part of #8511.

@mprobst

This comment has been minimized.

Contributor

mprobst commented May 28, 2016

@rjamet PTAL from a security perspective.
@mhevery PTAL for the new API addition (see public_api_spec.ts).

* `XSRFHandler` allows customizing how the application protects itself against Cross Site Request
* Forgery (XSRF) attacks. By default, Angular will look for a cookie called `'XSRF-TOKEN'`, and set
* an HTTP request header called `'X-XSRF-TOKEN'` with the value of the cookie on each request,
* allowing the server side to validate that the request comes from its own front end.

This comment has been minimized.

@rjamet

rjamet May 30, 2016

Contributor

Somewhat out of scope, but it's probably the right place to put a warning saying that Angular won't do that for you, and your backend has to check that in every relevant api point ?

@rjamet

This comment has been minimized.

Contributor

rjamet commented May 30, 2016

LGTM on the code, +@koto and @molnarg anyways.

However, this might need more doc, or links to https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF) for instance ? The problem is straightforward, but it's not obvious how Angular having this automatic header addition from cookie values helps, and what should a developer do with this to prevent issues.

configureRequest(req: Request) {
let xsrfToken = getDOM().getCookie(this.cookieName);
if (xsrfToken && !req.headers.has(this.headerName)) req.headers.set(this.headerName, xsrfToken);
}

This comment has been minimized.

@koto

koto May 30, 2016

Usually the GET requests don't need the XSRF token, but if Angular 1 did it for GET as well (I don't know that), it's better to have backwards compatibility here.

This comment has been minimized.

@rjamet

rjamet May 31, 2016

Contributor

I think it did, a quick review of the doc and implementation doesn't seem to discriminate on that (doc at https://github.com/angular/angular.js/blob/0727bfc141db6e60bce2fb1e09ad4f53963dec5d/src/ng/http.js#L770)

This comment has been minimized.

@mprobst

mprobst May 31, 2016

Contributor

Yeah, not needed, but I think it's better to make it a decision of the server side when to enforce XSRF, and just unconditionally send the headers by default here.

@koto

This comment has been minimized.

koto commented May 30, 2016

LGTM (modulo the notes above).

@molnarg

This comment has been minimized.

molnarg commented May 31, 2016

LGTM

@mprobst

This comment has been minimized.

Contributor

mprobst commented May 31, 2016

@rjamet I added a link in a somewhat random location. We're working on the security documentation, I plan to link to a central "here's all about security in Angular 2" doc once we have that.

@@ -164,7 +191,8 @@ export const HTTP_PROVIDERS: any[] = [
BrowserXhr,
provide(RequestOptions, {useClass: BaseRequestOptions}),
provide(ResponseOptions, {useClass: BaseResponseOptions}),
XHRBackend
XHRBackend,
provide(XSRFHandler, {useValue: new CookieXSRFHandler()}),

This comment has been minimized.

@vicb

vicb May 31, 2016

Contributor

useClass ?

This comment has been minimized.

@mprobst

mprobst May 31, 2016

Contributor

Nope. Our injector does not support arguments with default values, it'll complain about a binding for String missing.

constructor(private _browserXHR: BrowserXhr, private _baseResponseOptions: ResponseOptions) {}
constructor(
private _browserXHR: BrowserXhr, private _baseResponseOptions: ResponseOptions,
private xsrfHandler: XSRFHandler) {}

This comment has been minimized.

@vicb

vicb May 31, 2016

Contributor

_xsrfHandler

This comment has been minimized.

@mprobst

mprobst May 31, 2016

Contributor

Done.

@@ -20,6 +20,11 @@ export abstract class Connection {
response: any; // TODO: generic of <Response>;
}
/** An XSRFHandler configures XSRF protection (e.g. via headers) on an HTTP request. */
export abstract class XSRFHandler {

This comment has been minimized.

@mhevery

mhevery May 31, 2016

Member

How about Strategy instead of Handler?

This comment has been minimized.

@mprobst

mprobst May 31, 2016

Contributor

Done.

*/
export class CookieXSRFHandler implements XSRFHandler {
constructor(
private cookieName: string = 'XSRF-TOKEN', private headerName: string = 'X-XSRF-TOKEN') {}

This comment has been minimized.

@vicb

vicb May 31, 2016

Contributor

private -> _ prefix

This comment has been minimized.

@mprobst

mprobst May 31, 2016

Contributor

Done.

* with different `cookieName` and `headerName` values. See the main HTTP documentation for more
* details.
*/
export class CookieXSRFHandler implements XSRFHandler {

This comment has been minimized.

@mhevery

mhevery May 31, 2016

Member

Handler -> Strategy

This comment has been minimized.

@mprobst

mprobst May 31, 2016

Contributor

Done.

@mhevery

This comment has been minimized.

Member

mhevery commented May 31, 2016

LGTM

feat(security): Automatic XSRF handling.
Automatically recognize XSRF protection cookies, and set a corresponding XSRF
header. Allows applications to configure the cookie names, or if needed,
completely override the XSRF request configuration by binding their own
XSRFHandler implementation.

Part of #8511.

@mprobst mprobst merged commit 4d793c4 into angular:master May 31, 2016

1 of 4 checks passed

ci/circleci CircleCI is running your tests
Details
continuous-integration/travis-ci/pr The Travis CI build is in progress
Details
continuous-integration/travis-ci/push The Travis CI build is in progress
Details
cla/google All necessary CLAs are signed
private _cookieName: string = 'XSRF-TOKEN', private _headerName: string = 'X-XSRF-TOKEN') {}
configureRequest(req: Request) {
let xsrfToken = getDOM().getCookie(this._cookieName);

This comment has been minimized.

@tlaverdure

tlaverdure Jun 17, 2016

Seems related to this issue - #9294

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment