2016-10-09 8 views
0

Ich habe Probleme mit der Verwendung von OAuthAuthentication mit IS4 und ASPNetCore. Nimm DamienBods (danke) Beispiel Identity Server mit AspNetIdentity versuchte OAuth mit Windows Server 2012 ADFS3 hinzuzufügen. Ich könnte mich mit dem externen ADFS authentifizieren, aber auf der Identity Server-Seite keine korrekten Ergebnisse erhalten. AccountController.ExternalLoginCallback: var info = await _signInManager.GetExternalLoginInfoAsync() gibt NULL zurück und bin zurück zur Anmeldeseite. Der folgende Code könnte einige Dinge haben, die keinen Sinn ergeben, da ich experimentierte. Gerade jetzt habe ich fast das Ende meiner Fähigkeiten erreicht, da mein Wissen in diesem Bereich nicht so gut ist. Jede Hilfe wird sehr geschätzt Meine Code-Dateien sind wie folgt:Identity Server 4 mit OAuth und ADFS

Startup.cs:

`

public Startup(IHostingEnvironment env) 
{ 
var builder = new ConfigurationBuilder() 
.SetBasePath(env.ContentRootPath) 
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) 
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true); 
     if (env.IsDevelopment()) 
     { 
      builder.AddUserSecrets(); 
     } 

     _environment = env; 

     builder.AddEnvironmentVariables(); 
     Configuration = builder.Build(); 
    } 

    public IConfigurationRoot Configuration { get; } 

    public void ConfigureServices(IServiceCollection services) 
    { 
     var cert = new X509Certificate2(Path.Combine(_environment.ContentRootPath, "damienbodserver.pfx"), ""); 

     services.AddMvc(); 

     services.AddDbContext<ApplicationDbContext>(options => 
      options.UseSqlite(Configuration.GetConnectionString("DefaultConnection"))); 

     services.AddAuthentication(); 

     services.AddIdentity<ApplicationUser, IdentityRole>() 
     .AddEntityFrameworkStores<ApplicationDbContext>() 
     .AddDefaultTokenProviders(); 



     services.AddTransient<IProfileService, IdentityWithAdditionalClaimsProfileService>(); 

     services.AddTransient<IEmailSender, AuthMessageSender>(); 
     services.AddTransient<ISmsSender, AuthMessageSender>(); 

    // services.AddAuthentication(); 
     //var builder = services.AddIdentityServer(options => 
     //{ 
     // //options. 
     //}); 

     services.AddDeveloperIdentityServer() 
      .SetSigningCredential(cert) 
      .AddInMemoryScopes(Config.GetScopes()) 
      .AddInMemoryClients(Config.GetClients()) 
      .AddInMemoryUsers(Config.GetUsers()) 
      .AddAspNetIdentity<ApplicationUser>() 
      .AddProfileService<IdentityWithAdditionalClaimsProfileService>(); 
    } 

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) 
    { 
     var certificate = new X509Certificate2(@"D:\Downloads\AspNet5IdentityServerAngularImplicitFlow-master\AspNet5IdentityServerAngularImplicitFlow-master\src\IdentityServerWithIdentitySQLite\signingCertificate.CER"); 

     loggerFactory.AddConsole(Configuration.GetSection("Logging")); 
     loggerFactory.AddDebug(); 

     if (env.IsDevelopment()) 
     { 
      app.UseDeveloperExceptionPage(); 
      app.UseDatabaseErrorPage(); 
      app.UseBrowserLink(); 
     } 
     else 
     { 
      app.UseExceptionHandler("/Home/Error"); 
     } 

     //app.UseJwtBearerAuthentication(new JwtBearerOptions 
     //{ 
     // AutomaticAuthenticate = true, 
     // AutomaticChallenge = true, 
     // SaveToken = true, 
     // TokenValidationParameters = new TokenValidationParameters 
     // { 
     //  //Iss  
     //  ValidateIssuer = true, 
     //  ValidIssuer = "http://FSSTARS-BO-ADFS.linkedgaming.com/adfs/services/trust", 
     //  // ValidIssuer = "7fe2cdc6-4c2d-4d92-bac9-990df31f669c", 

     //  ValidateAudience = true, 
     //  ValidAudience = "microsoft:identityserver:StarsRelyingTrustProvider", 
     //  ValidateIssuerSigningKey = true, 

     //  IssuerSigningKey = new X509SecurityKey(certificate), 

     //  ValidateLifetime = true, 
     //  ClockSkew = TimeSpan.Zero 

     // }, 
     //}); 

     app.UseStaticFiles(); 

     app.UseIdentity(); 

     app.UseCookieAuthentication(new CookieAuthenticationOptions 
     { 
      AuthenticationScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme, 

      AutomaticAuthenticate = false, 
      AutomaticChallenge = false 
     }); 

     app.UseOAuthAuthentication(new OAuthOptions() 
     { 
      DisplayName = "ADFS", 
      //AutomaticAuthenticate = false, 
      //AutomaticChallenge = false, 
      AuthenticationScheme = "OAuth2", 
      SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme, 
      SaveTokens = true, 

      //ClientId = "7fe2cdc6-4c2d-4d92-bac9-990df31f669c", 
      ClientId = "9fe2cdc6-4c2d-4d92-bac9-990df31f669g", 
      ClientSecret = "notneeded", 
      CallbackPath = new   Microsoft.AspNetCore.Http.PathString("/About"), 
      AuthorizationEndpoint = "https://fsstars-bo-adfs.linkedgaming.com/adfs/oauth2/authorize", 
      TokenEndpoint = "https://fsstars-bo-adfs.linkedgaming.com/adfs/oauth2/token", 
      Events = new OAuthEvents 
      { 
       OnRedirectToAuthorizationEndpoint = context => 
       { 
        context.Response.Redirect($"{context.RedirectUri}&resource=StarsRelyingTrustProvider"); 
        return Task.FromResult(0); 
       } 
      }, 


     }); 

     app.UseIdentityServer(); 
     app.UseMvc(routes => 
     { 
      routes.MapRoute(
       name: "default", 
       template: "{controller=Home}/{action=Index}/{id?}"); 
     }); 
    } 
} 
} 
` 

AccountController.cs:

`[Authorize] 
public class AccountController : Controller 
{ 
public AccountController(
IIdentityServerInteractionService interaction, 
IPersistedGrantService persistedGrantService, 
UserManager<ApplicationUser> userManager, 
SignInManager<ApplicationUser> signInManager, 
IEmailSender emailSender, 
ISmsSender smsSender, 
ILoggerFactory loggerFactory) 
{ 
_interaction = interaction; 
_persistedGrantService = persistedGrantService; 
_userManager = userManager; 
_signInManager = signInManager; 
_emailSender = emailSender; 
_smsSender = smsSender; 
_logger = loggerFactory.CreateLogger<AccountController>(); 
} 
    // 
    // GET: /Account/Login 
    [HttpGet] 
    [AllowAnonymous] 
    public IActionResult Login(string returnUrl = null) 
    { 
     ViewData["ReturnUrl"] = returnUrl; 
     return View(); 
    } 

    // 
    // POST: /Account/Login 
    [HttpPost] 
    [AllowAnonymous] 
    [ValidateAntiForgeryToken] 
    public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null) 
    { 
     ViewData["ReturnUrl"] = returnUrl; 
     if (ModelState.IsValid) 
     { 
      // This doesn't count login failures towards account lockout 
      // To enable password failures to trigger account lockout, set lockoutOnFailure: true 
      var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false); 
      if (result.Succeeded) 
      { 
       _logger.LogInformation(1, "User logged in."); 
       return RedirectToLocal(returnUrl); 
      } 
      if (result.RequiresTwoFactor) 
      { 
       return RedirectToAction(nameof(SendCode), new { ReturnUrl = returnUrl, RememberMe = model.RememberMe }); 
      } 
      if (result.IsLockedOut) 
      { 
       _logger.LogWarning(2, "User account locked out."); 
       return View("Lockout"); 
      } 
      else 
      { 
       ModelState.AddModelError(string.Empty, "Invalid login attempt."); 
       return View(model); 
      } 
     } 

     // If we got this far, something failed, redisplay form 
     return View(model); 
    } 


    // 
    // POST: /Account/LogOff 
    //[HttpPost] 
    //[ValidateAntiForgeryToken] 
    //public async Task<IActionResult> LogOff() 
    //{ 
    // await _signInManager.SignOutAsync(); 
    // _logger.LogInformation(4, "User logged out."); 
    // return RedirectToAction(nameof(HomeController.Index), "Home"); 
    //} 

    // 
    // POST: /Account/ExternalLogin 
    [HttpPost] 
    [AllowAnonymous] 
    [ValidateAntiForgeryToken] 
    public IActionResult ExternalLogin(string provider, string returnUrl = null) 
    { 
     // Request a redirect to the external login provider. 
     var redirectUrl = Url.Action("ExternalLoginCallback", "Account", new { ReturnUrl = returnUrl }); 
     var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl); 
     return Challenge(properties, provider); 
    } 

    // 
    // GET: /Account/ExternalLoginCallback 
    [HttpGet] 
    [AllowAnonymous] 
    public async Task<IActionResult> ExternalLoginCallback(
     string returnUrl = null, string remoteError = null) 
    { 
     if (remoteError != null) 
     { 
      ModelState.AddModelError(string.Empty, $"Error from external provider: {remoteError}"); 
      return View(nameof(Login)); 
     } 
     var info = await _signInManager.GetExternalLoginInfoAsync(); 
     if (info == null) 
     { 
      return RedirectToAction(nameof(Login)); 
     } 

     // Sign in the user with this external login provider if the user already has a login. 
     var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false); 
     if (result.Succeeded) 
     { 
      _logger.LogInformation(5, "User logged in with {Name} provider.", info.LoginProvider); 
      return RedirectToLocal(returnUrl); 
     } 
     if (result.RequiresTwoFactor) 
     { 
      return RedirectToAction(nameof(SendCode), new { ReturnUrl = returnUrl }); 
     } 
     if (result.IsLockedOut) 
     { 
      return View("Lockout"); 
     } 
     else 
     { 
      // If the user does not have an account, then ask the user to create an account. 
      ViewData["ReturnUrl"] = returnUrl; 
      ViewData["LoginProvider"] = info.LoginProvider; 
      var email = info.Principal.FindFirstValue(ClaimTypes.Email); 
      return View("ExternalLoginConfirmation", new ExternalLoginConfirmationViewModel { Email = email }); 
     } 
    } 

    // 
    // POST: /Account/ExternalLoginConfirmation 
    [HttpPost] 
    [AllowAnonymous] 
    [ValidateAntiForgeryToken] 
    public async Task<IActionResult> ExternalLoginConfirmation(ExternalLoginConfirmationViewModel model, string returnUrl = null) 
    { 
     if (ModelState.IsValid) 
     { 
      // Get the information about the user from the external login provider 
      var info = await _signInManager.GetExternalLoginInfoAsync(); 
      if (info == null) 
      { 
       return View("ExternalLoginFailure"); 
      } 
      var user = new ApplicationUser { UserName = model.Email, Email = model.Email }; 
      var result = await _userManager.CreateAsync(user); 
      if (result.Succeeded) 
      { 
       result = await _userManager.AddLoginAsync(user, info); 
       if (result.Succeeded) 
       { 
        await _signInManager.SignInAsync(user, isPersistent: false); 
        _logger.LogInformation(6, "User created an account using {Name} provider.", info.LoginProvider); 
        return RedirectToLocal(returnUrl); 
       } 
      } 
      AddErrors(result); 
     } 

     ViewData["ReturnUrl"] = returnUrl; 
     return View(model); 
    } 

    // GET: /Account/ConfirmEmail 
    [HttpGet] 
    [AllowAnonymous] 
    public async Task<IActionResult> ConfirmEmail(string userId, string code) 
    { 
     if (userId == null || code == null) 
     { 
      return View("Error"); 
     } 
     var user = await _userManager.FindByIdAsync(userId); 
     if (user == null) 
     { 
      return View("Error"); 
     } 
     var result = await _userManager.ConfirmEmailAsync(user, code); 
     return View(result.Succeeded ? "ConfirmEmail" : "Error"); 
    } 

    /// <summary> 
    /// Show logout page 
    /// </summary> 
    [HttpGet] 
    public IActionResult Logout(string logoutId) 
    { 
     var vm = new LogoutViewModel 
     { 
      LogoutId = logoutId 
     }; 

     return View(vm); 
    } 

    /// <summary> 
    /// Handle logout page postback 
    /// </summary> 
    [HttpPost] 
    [ValidateAntiForgeryToken] 
    public async Task<IActionResult> Logout(LogoutViewModel model) 
    { 
     var user = HttpContext.User.Identity.Name; 
     var subjectId = HttpContext.User.Identity.GetSubjectId(); 

     // delete authentication cookie 
     await HttpContext.Authentication.SignOutAsync(); 


     // set this so UI rendering sees an anonymous user 
     HttpContext.User = new ClaimsPrincipal(new ClaimsIdentity()); 

     // get context information (client name, post logout redirect URI and iframe for federated signout) 
     var logout = await _interaction.GetLogoutContextAsync(model.LogoutId); 

     var vm = new LoggedOutViewModel 
     { 
      PostLogoutRedirectUri = logout?.PostLogoutRedirectUri, 
      ClientName = logout?.ClientId, 
      SignOutIframeUrl = logout?.SignOutIFrameUrl 
     }; 


     await _persistedGrantService.RemoveAllGrantsAsync(subjectId, "angular2client"); 

     return View("LoggedOut", vm); 
    } 

    #region Helpers 

    private void AddErrors(IdentityResult result) 
    { 
     foreach (var error in result.Errors) 
     { 
      ModelState.AddModelError(string.Empty, error.Description); 
     } 
    } 

    private Task<ApplicationUser> GetCurrentUserAsync() 
    { 
     return _userManager.GetUserAsync(HttpContext.User); 
    } 

    private IActionResult RedirectToLocal(string returnUrl) 
    { 
     if (Url.IsLocalUrl(returnUrl)) 
     { 
      return Redirect(returnUrl); 
     } 
     else 
     { 
      return RedirectToAction(nameof(HomeController.Index), "Home"); 
     } 
    } 

Antwort

2

_signInManager.GetExternalLoginInfoAsync() schlägt fehl, weil Identität das von Ihnen verwendete Schema nicht kennt. Sie müssen eine ähnliche Methode wie GetExternalLoginInfoAsync erstellen, um Ihre Informationen zu extrahieren.

private async Task<ExternalLoginInfo> AuthenticationManager_GetExternalLoginInfoAsync_Workaround() 
     { 
      ExternalLoginInfo loginInfo = null; 
      var info = await HttpContext.Authentication.GetAuthenticateInfoAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme); 
      var auth = new AuthenticateContext(IdentityServerConstants.ExternalCookieAuthenticationScheme); 
      // read external identity from the temporary cookie 
      await HttpContext.Authentication.AuthenticateAsync(auth); 

      if (auth.Principal == null || auth.Properties == null) 
      { 
       throw new Exception("External authentication error"); 
      } 

      // retrieve claims of the external user 
      var claims = auth.Principal.Claims.ToList(); 


      // try to determine the unique id of the external user - the most common claim type for that are the sub claim and the NameIdentifier 
      // depending on the external provider, some other claim type might be used 
      var userIdClaim = claims.FirstOrDefault(x => x.Type == JwtClaimTypes.Subject); 
      if (userIdClaim == null) 
      { 
       userIdClaim = claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier); 
      } 
      if (userIdClaim == null) 
      { 
       throw new Exception("Unknown userid"); 
      } 

      string userObjectID = auth.Principal.FindFirst(ClaimTypes.NameIdentifier).Value; 
      // remove the user id claim from the claims collection and move to the userId property 
      // also set the name of the external authentication provider 
      claims.Remove(userIdClaim); 
      var provider = userIdClaim.Issuer; 
      var userId = userIdClaim.Value; 

      var displayName = auth.Principal.FindFirstValue(ClaimTypes.GivenName); 

      AuthenticationProperties props = null; 


      loginInfo = new ExternalLoginInfo(auth.Principal, userIdClaim.Issuer, userIdClaim.Value, displayName)   

      return loginInfo; 
     } 

Und ich hat dieses Bild auf dem ExternalLoginCallback

var info = await _signInManager.GetExternalLoginInfoAsync(); 
     if (info == null) 
     { 
      info = await AuthenticationManager_GetExternalLoginInfoAsync_Workaround(); 
      if (info == null) 
      { 
       return RedirectToAction(nameof(Login)); 
      } 

     } 

Hoffe, es hilft, sich eine Arbeit noch im Gange.

Verwandte Themen