Authentication approach to be use in asp.net Web api and angular js

此生再无相见时 提交于 2019-12-04 12:54:16

The best way to do it is with token authentication. In summary it works like this:

  • A POST /api/login route on the server takes in a username + password, checks that they are valid against the database, then generates and returns a refresh token (which can just be a random string or GUID). The refresh token is also stored in the database next to the user, overwriting the previous refresh token
  • A GET /api/access-token route on the server takes in a username + refresh token, checks that they match in the database, then generates and returns an access token
  • Any other /api/* routes require a valid access token to be in the header of the request, otherwise they assume the user does not have a valid login

The access token is a data object that has been encrypted using a secret key that only the server knows. It should contain the username, an expiry date (usually ~10mins from when the token was generated), and any permissions or misc data about the user. Because it is encrypted with a secret key, it cannot be forged by an attacker.

You will need to implement these routes on your server.

If you are using OWIN, here is how you can use the Microsoft.Owin.Security.OAuth NuGet package to do the encryption bit for you:

Have this in your startup configuration:

using System.Web.Http;
using Microsoft.Owin;
using Microsoft.Owin.Security.OAuth;
using Owin;

[assembly: OwinStartup(typeof(MyProject.Startup))]
namespace MyProject
{
    public class Startup
    {
        public static OAuthBearerAuthenticationOptions OAuthBearerOptions { get; private set; }

        public void Configuration(IAppBuilder app)
        {
            var config = new HttpConfiguration();

            OAuthBearerOptions = new OAuthBearerAuthenticationOptions();
            app.UseOAuthBearerAuthentication(OAuthBearerOptions);

            // Configure Web API to use only bearer token authentication.
            config.SuppressDefaultHostAuthentication();
            config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));

            app.UseWebApi(config);
        }
    }
}

Then, you can generate a ticket (which is the unencrypted access token) and encrypt it like this:

var identity = new ClaimsIdentity(new[] {
    new Claim(ClaimTypes.Email, "users email"),
    // other business specific claims e.g. "IsAdmin"
});
var ticket = new AuthenticationTicket(identity, new AuthenticationProperties(
    {
        ExpiresUtc = DateTime.UtcNow.AddMinutes(10)
    }));
var accessToken = MyProject.Startup.OAuthBearerOptions.AccessTokenFormat.Protect(ticket);

In Angular you need to setup a way to login, a way to get a new access token when it expires, and a way to pass the access token in the header of every API request. I recommend storing the refresh token and access token in local storage (or cookie for old browsers), and using $httpProvider.interceptors.push to add an interceptor for every $http call. The interceptor can then add the access token to the header like this: config.headers['Authorization'] = 'Bearer ' + accessToken;

Define the interceptor in angular:

angular.module('app').service('authenticationInterceptor', ['$q', function($q) {
    this.request = function(config) {
        var accessToken = // ... get the access token from local storage / cookie
        config.headers['Authorization'] = 'Bearer ' + accessToken;
        return config;
    };
}]);

Add it to $httpProvider:

angular.module('app').config(['$httpProvider', ($httpProvider: ng.IHttpProvider) => {
    $httpProvider.interceptors.push('authenticationInterceptor');
}]);

This is a very broad question to answer and there is no chance of doing it in single answer.

What I can say to you is "token authentication" with Outh2 should do the job; that's the easiest way to work with Angular and WebAPI when we talk about security. Cookies are not the right solution in this case.

Check this article for more details on how to implement a full working Token Based Authentication using ASP.NET Web API 2, Owin, and Identity. That article really helped me in many ways. Eventually, when you will have a sample solution, you can came back here and ask for more "details".

BTW, I read this "comment" inside you code:

//Now the tricky parts comes like after authenticating user should i //just store the user id in my session like this Session["userid]=id or //Should i go for storing whole user object in my cookie as i have read

Personally, I think session is evil. I'm not the only one. Anyway, if you want to use "session" in web.api world, it doesn't come out for free, you have to activate it. So if for any reason you need to use it, check this.

Hope it helps :)

The best way is to use json web token (JWT)...

Satellizer is a great library to add to your Angular app https://github.com/sahat/satellizer

HTML

    <form method="post" ng-submit="login()" name="loginForm">
      <div class="form-group has-feedback">
        <input class="form-control input-lg" type="text" name="email" ng-model="user.email" placeholder="Email" required autofocus>
        <span class="ion-at form-control-feedback"></span>
      </div>
      <div class="form-group has-feedback">
        <input class="form-control input-lg" type="password" name="password" ng-model="user.password" placeholder="Password" required>
        <span class="ion-key form-control-feedback"></span>
      </div>
      <button type="submit" ng-disabled="loginForm.$invalid" class="btn btn-lg  btn-block btn-success">Log in</button>
      <br/>
      <p class="text-center text-muted">
        <small>Don't have an account yet? <a href="/#/signup">Sign up</a></small>
      </p>
      <div class="signup-or-separator">
        <h6 class="text">or</h6>
        <hr>
      </div>
    </form>

JS

angular.module('MyApp')
  .controller('LoginCtrl', function($scope, $auth) {

     $scope.login = function() {
        $auth.login($scope.user)
          .then(function() {
            toastr.success('You have successfully signed in!');
            $location.path('/');
          })
          .catch(function(error) {
            toastr.error(error.data.message, error.status);
          });
        };    
  });

Server-side, they have a C# example at https://github.com/sahat/satellizer/tree/master/examples/server/c%23

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!