在Nancy中使用来自OWIN上下文的用户

时间:2017-06-16 11:13:28

标签: f# authorization owin nancy katana

我有一个由OWIN托管的Nancy项目。目前它有自己的用户身份验证。计划是改变它,使我的项目与外部认证模型兼容 - 即基于SAML;我有一个本地身份提供商,并设法处理我的服务和IdP之间的通信。我通过使用Kentor.AuthServices库(https://github.com/KentorIT/authservices

实现了这一目标
let CreateSPOptions() : SPOptions =
    let spOptions = new SPOptions()
    spOptions.EntityId <- new EntityId("<my_service_ID>")
    spOptions.ReturnUrl <- new Uri("http://localhost:5012/login")
    spOptions.MinIncomingSigningAlgorithm <- "http://www.w3.org/2000/09/xmldsig#rsa-sha1"
    spOptions

let ConfigureAuthOptions() : KentorAuthServicesAuthenticationOptions =
    let spOptions = CreateSPOptions()
    let authServicesOptions = new KentorAuthServicesAuthenticationOptions(false)
    authServicesOptions.SPOptions <- spOptions
    let idp = new IdentityProvider(new EntityId("<my_IdP_ID>"), spOptions)
    idp.AllowUnsolicitedAuthnResponse <- true
    idp.Binding <- Saml2BindingType.HttpRedirect
    idp.MetadataLocation <- @"Metadata\provider.xml"
    authServicesOptions.IdentityProviders.Add(idp);
    authServicesOptions

let Configure (app : IAppBuilder) =
    let cookieOptions = new CookieAuthenticationOptions()
    cookieOptions.LoginPath <- new PathString("/Login")
    cookieOptions.LogoutPath <- new PathString("/Logout")
    cookieOptions.AuthenticationType <- "KentorAuthServices"
    cookieOptions.AuthenticationMode <- AuthenticationMode.Active
    cookieOptions.Provider <- new CookieAuthenticationProvider()

    app.UseCookieAuthentication(cookieOptions) |> ignore
    app.SetDefaultSignInAsAuthenticationType("KentorAuthServices")
    app.UseKentorAuthServicesAuthentication(ConfigureAuthOptions()) |> ignore
    app

但是,因此用户信息现在存储在Owin上下文中,因此我不能依赖this.Context.CurrentUser(其中this指的是当前的Nancy模块),我可以&# 39;使用以下方法保护我的模块:

type SecuredModule() as this =
    inherit NancyModule()

    do
        this.RequiresAuthentication()

        this.Get.["/"] <- ....

我知道Nancy.MSOwinSecurity包中提供的功能允许我引用OwinContext,例如。

type SecuredModule() as this =
    inherit NancyModule()

    do
        this.RequiresMSOwinAuthentication()

        this.Get.["/"] <- ...

但问题是,有许多与项目相关的测试假设用户信息存储在Nancy上下文中。绝大多数测试都基于模拟对象:

let createBrowser rootFolder =
    let docStore = DocumentStore(rootFolder)
    let config (w:ConfigurableBootstrapper.ConfigurableBootstrapperConfigurator) = 
        w.Module(new UnsecuredModule(docStore))
         .Module(new SecuredModule(docStore)) 
         .RequestStartup(fun _ _ (context: NancyContext) ->
            context.CurrentUser <- new UserIdentity("MyServiceUnitTests", Seq.empty)) 
        |> ignore

在处理来自我的IdP的响应并手动覆盖context.CurrentUser时,我尝试了相同的操作,但重定向后信息丢失了:

type LoginModule(userDatabase: UserDatabase) as this = 
    inherit NancyModule()

    do
        this.Get.["/login"] <-
            fun _ ->
                match this.Context.GetMSOwinUser() with
                | null ->
                    let authenticationManager = this.Context.GetAuthenticationManager();
                    let properties = new AuthenticationProperties()
                    properties.RedirectUri <- "/Web.Documents/login"
                    authenticationManager.Challenge(properties, "KentorAuthServices")
                    HttpStatusCode.Unauthorized |> box
                | user ->
                    let userName = user.Identity.Name
                    let ipAddress = this.Context.Request.UserHostAddress
                    Log.Info "{@user} {@ipaddress} logged in" [ 
                        "user"      => userName
                        "ipaddress" => ipAddress 
                    ]
                    this.Context.CurrentUser <- new UserIdentity("MyServiceUnitTests", Seq.empty)
                    this.Context.GetRedirect("~/") |> box

显然,我不想对我的服务进行太多更改。理想情况下,我希望以某种方式将用户信息移动到Nancy Context - 然后我很乐意去,因为我也不需要调整~50个测试。什么是最好的解决方案?

0 个答案:

没有答案