Ситуация: У меня есть проект Web API 2, который действует как сервер авторизации (конечная точка маркера) и сервер ресурсов. Я использую шаблон, который выходит из коробки с API ASP.Net Web минус любая ссылка MVC. StartAuth настроен следующим образом:
public void ConfigureAuth(IAppBuilder app)
{
// Configure the db context and user manager to use a single instance per request
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
// Enable the application to use a cookie to store information for the signed in user
// and to use a cookie to temporarily store information about a user logging in with a third party login provider
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
// Configure the application for OAuth based flow
PublicClientId = "self";
OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/Token"),
Provider = new ApplicationOAuthProvider(PublicClientId),
AuthorizeEndpointPath = new PathString("/Account/ExternalLogin"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
// In production mode set AllowInsecureHttp = false
AllowInsecureHttp = true
};
// Enable the application to use bearer tokens to authenticate users
app.UseOAuthBearerTokens(OAuthOptions);
var facebookAuthenticationOptions = new FacebookAuthenticationOptions()
{
AppId = ConfigurationManager.AppSettings["Test_Facebook_AppId"],
AppSecret = ConfigurationManager.AppSettings["Test_Facebook_AppSecret"],
//SendAppSecretProof = true,
Provider = new FacebookAuthenticationProvider
{
OnAuthenticated = (context) =>
{
context.Identity.AddClaim(new System.Security.Claims.Claim("FacebookAccessToken", context.AccessToken));
return Task.FromResult(0);
}
}
};
facebookAuthenticationOptions.Scope.Add("email user_about_me user_location");
app.UseFacebookAuthentication(facebookAuthenticationOptions);
}
Клиент MVC 5 (другой проект) использует приложение веб-API для авторизации и данных. Ниже приведен код для извлечения маркера Bearer в случае сохранения имени пользователя/пароля:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
if (!ModelState.IsValid)
{
model.ExternalProviders = await GetExternalLogins(returnUrl);
return View(model);
}
var client = Client.GetClient();
var response = await client.PostAsync("Token",
new StringContent(string.Format("grant_type=password&username={0}&password={1}", model.Email, model.Password), Encoding.UTF8));
if (response.IsSuccessStatusCode)
{
return RedirectToLocal(returnUrl);
}
return View();
}
Проблема
Я мог бы получить токен-носитель, а затем добавить его в заголовок авторизации для последующих вызовов. Я думаю, что это будет нормально в случае приложения Angular или SPA. Но я думаю, что в MVC должно быть что-то, что обрабатывает его для меня, например, автоматически сохраняет его в файле cookie и отправляет cookie на последующие запросы. Я много искал, и есть записи, которые намекают на это (Регистрация внешних интерфейсов Web API 2 из нескольких клиентов API с идентификатором OWIN), но я не был способный выяснить, что делать после того, как я получу токен.
Нужно ли добавить что-то в приложение MVC Startup.Auth?
В идеале мне нужны функции, которые AccountController в шаблоне ASP.Net(MVC + Web API) выдает из окна (логины, регистр, внешние логины, пароль для забывания и т.д. и т.д.), но с помощью MVC и веб-API в разных проектах.
Есть ли шаблон или репозиторий git, который имеет этот код котельной плиты?
Спасибо заранее!
Обновление Включая предложения @FrancisDucharme, ниже приведен код для GrantResourceOwnerCredentials().
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
var userManager = context.OwinContext.GetUserManager<ApplicationUserManager>();
ApplicationUser user = await userManager.FindAsync(context.UserName, context.Password);
if (user == null)
{
context.SetError("invalid_grant", "The user name or password is incorrect.");
return;
}
ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager,
OAuthDefaults.AuthenticationType);
ClaimsIdentity cookiesIdentity = await user.GenerateUserIdentityAsync(userManager,
CookieAuthenticationDefaults.AuthenticationType);
AuthenticationProperties properties = CreateProperties(user.UserName);
AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, properties);
//Add a response cookie...
context.Response.Cookies.Append("Token", context.Options.AccessTokenFormat.Protect(ticket));
context.Validated(ticket);
context.Request.Context.Authentication.SignIn(cookiesIdentity);
}
Но я все еще не могу получить этот Cookie или выяснить, что делать дальше.
Вопросы для повторения:
- Каким будет правильный способ аутентификации, авторизации и вызова методов Web API (Auth и Resource Server) из MVC-клиента?
- Есть ли шаблонный шаблон или шаблон для AccountController, который выполняет основную сантехнику (вход, регистрация - внутренний/внешний, забыли пароль и т.д.)?