Anti forgery with token API and angular

后端 未结 2 1855
情书的邮戳
情书的邮戳 2020-12-12 01:44

I am working on Angular 6 application with SSO login and .net core web API. The code hits the back end on /token url first time which is a post operation. How do I do the an

2条回答
  •  时光说笑
    2020-12-12 02:28

    I'm not sure if that's what you're looking for, but I'll try to explain how I achieved it in a similar case.

    First of all Angular has built in helpers for XSRF handling:

    • https://angular.io/guide/security#http
    • https://angular.io/api/common/http/HttpClientXsrfModule
    • https://angular.io/api/common/http/HttpXsrfTokenExtractor

    So the hardest part is to create custom XSRF middleware at api level.

    I did it some time ago for one of my apps which was built with Angular 6 on the front and ASP.NET Core WebApi on the back-end.

    Article which help me with it:

    • https://www.domstamand.com/secure-your-angularasp-net-core-application-with-anti-forgery-token/

    Your middleware could look like this:

    public class AntiForgeryTokenMiddleware
    {
        private readonly RequestDelegate _next;
        private readonly IAntiforgery _antiforgery;
    
        public AntiForgeryTokenMiddleware(RequestDelegate next, IAntiforgery antiforgery)
        {
            _next = next;
            _antiforgery = antiforgery;
        }
    
        public Task Invoke(HttpContext context)
        {
            if (context.Request.Path.Value.IndexOf("/your api endpoint, e.g. /api", StringComparison.OrdinalIgnoreCase) != -1)
            {
                var tokens = _antiforgery.GetAndStoreTokens(context);
                context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken, new CookieOptions { HttpOnly = false, Secure = false });
            }
            return _next(context);
        }
    }
    

    Then as per mentioned article you have to add it to services in ConfigureServices method of Startup class:

    services.AddAntiforgery(options => options.HeaderName = "X-XSRF-TOKEN");
    

    And use it in Configure method:

    app.UseAntiforgeryToken();
    

    And of course to make use of it you have to decorate your api methods with [ValidateAntiForgeryToken] attribute.

    Then in your Angular app you could create HttpInterceptor to send token only when it's needed.

        @Injectable()
        export class XsrfInterceptor implements HttpInterceptor {
    
        constructor(private tokenExtractor: HttpXsrfTokenExtractor) {}
    
        private actions: string[] = ["POST", "PUT", "DELETE"];
        private forbiddenActions: string[] = ["HEAD", "OPTIONS"];
    
        intercept(request: HttpRequest, next: HttpHandler): Observable> {
            let token = this.tokenExtractor.getToken();
            let permitted =  this.findByActionName(request.method, this.actions);
            let forbidden =  this.findByActionName(request.method, this.forbiddenActions);;
    
            if (permitted !== undefined && forbidden === undefined && token !== null) {
                request = request.clone({ setHeaders: { "X-XSRF-TOKEN": token } });
            }
    
            return next.handle(request);
        }
    
        private findByActionName(name: string, actions: string[]): string {
            return actions.find(action => action.toLocaleLowerCase() === name.toLocaleLowerCase());
        }
    }
    

提交回复
热议问题