Проблема аутентификации - безопасное веб-приложение с сервером аутентификации API - PullRequest
1 голос
/ 20 сентября 2019

Я начал создавать программную архитектуру, в которой у меня есть:

  • Auth_API - в качестве сервера аутентификации
  • Resource_API - в качестве API ресурса (защищен Auth_API)
  • WebApplication (mvc) - приложение внешнего интерфейса (защищено Auth_API).

Основано на статье https://bitoftech.net/2014/06/01/token-based-authentication-asp-net-web-api-2-owin-asp-net-identity/. Я успешно провел проверку подлинности Google.

WebApp== перенаправляет на ==> Auth_API == challenge ==> Google ==> API получает externalAccessToken, регистрирует пользователя локально и возвращает localAccessToken

Теперь все в порядке, когда я хочу использоватьавторизация на предъявителя (с использованием локального токена доступа).Но я также хочу войти в приложение ASP MVC с помощью (cookie?) ClaimsIdentity.

Я думал о переходе на JWT, но я не уверен, куда мне идти ...

Бит кода:

  1. Auth_API - получить токен локального доступа

    /// <summary>
    /// Returns local access token for already registered users
    /// </summary>
    /// <param name="provider"></param>
    /// <param name="externalAccessToken"></param>
    /// <returns></returns>
    [AllowAnonymous]
    [HttpGet]
    [Route("ObtainLocalAccessToken")]
    public async Task<IHttpActionResult> ObtainLocalAccessToken(string provider, string externalAccessToken)
    {
        if (string.IsNullOrWhiteSpace(provider) || string.IsNullOrWhiteSpace(externalAccessToken))
        {
            return BadRequest("Provider or external access token is not sent");
        }
    
        var verifiedAccessToken = await VerifyExternalAccessToken(provider, externalAccessToken);
        if (verifiedAccessToken == null)
        {
            return BadRequest("Invalid Provider or External Access Token");
        }
    
        IdentityUser user = await _repo.FindAsync(new UserLoginInfo(provider, verifiedAccessToken.user_id));
    
        bool hasRegistered = user != null;
    
        if (!hasRegistered)
        {
            return BadRequest("External user is not registered");
        }
    
        //generate access token response
        var accessTokenResponse = GenerateLocalAccessTokenResponse(user.UserName);
    
        return Ok(accessTokenResponse);
    }
    
  2. Создать алгоритм локального токена доступа

        private JObject GenerateLocalAccessTokenResponse(string userName)
    {
        var tokenExpiration = TimeSpan.FromDays(1);
    
        ClaimsIdentity identity = new ClaimsIdentity(OAuthDefaults.AuthenticationType);
    
        identity.AddClaim(new Claim(ClaimTypes.Name, userName));
        identity.AddClaim(new Claim("role", "user"));
    
        var props = new AuthenticationProperties()
        {
            IssuedUtc = DateTime.UtcNow,
            ExpiresUtc = DateTime.UtcNow.Add(tokenExpiration),
        };
    
        var ticket = new AuthenticationTicket(identity, props);
    
        var accessToken = Startup.OAuthBearerOptions.AccessTokenFormat.Protect(ticket);
    
        JObject tokenResponse = new JObject(
                                    new JProperty("userName", userName),
                                    new JProperty("access_token", accessToken),
                                    new JProperty("token_type", "bearer"),
                                    new JProperty("expires_in", tokenExpiration.TotalSeconds.ToString()),
                                    new JProperty(".issued", ticket.Properties.IssuedUtc.ToString()),
                                    new JProperty(".expires", ticket.Properties.ExpiresUtc.ToString())
        );
    
        return tokenResponse;
    }
    
  3. Веб-приложение - частьдействия входа в систему:

        if (hasLocalAccount)
        {
            var client = new RestClient(baseApiUrl);
            var externalLoginUrl = "Account/ObtainLocalAccessToken";
            var externalLoginRequest = new RestRequest(externalLoginUrl, Method.GET);
            externalLoginRequest.AddQueryParameter("provider", provider);
            externalLoginRequest.AddQueryParameter("externalAccessToken", externalAccessToken);
    
            var externalLoginResponse = client.Execute(externalLoginRequest);
    
            if (externalLoginResponse.IsSuccessful)
            {
                JObject response = JObject.Parse(externalLoginResponse.Content);
                string localAccessToken = response["access_token"].Value<string>();
                string localTokenExpiresIn = response["expires_in"].Value<string>();
    
                // WHAT TO DO WHERE TO SIGN IN A USER ??? 
                //AuthenticationTicket ticket = Startup.OAuthBearerOptions.AccessTokenFormat.Unprotect(localAccessToken);   <== this returns NULL
    
                return RedirectToAction("Index", "Home");
            }
        }
    
...