设置 OAuth
使用 Google OAuth 最简单的方法是等到 Saturn 的下一个版本,届时 Saturn 将包括use_google_oauth
我刚刚添加的功能。 :-) 看源代码 https://github.com/SaturnFramework/Saturn/blob/master/src/Saturn.Extensions.Authorization/OAuth.fs如果您对它的工作原理感兴趣,但恐怕您无法自己实现use_custom_oauth
因为您会遇到类型错误(底层 ASP.NET 代码有一个 GoogleOptions 类,并且use_custom_oauth
想要一个 OAuthOptions 类,但它们不兼容)。
要使用它,请将以下内容添加到您的application
CE:
use_google_oauth googleClientId googleClientSecret "/oauth_callback_google" []
最后一个参数应该是一个序列string * string
表示键和值的对:您可以使用元组列表或传递的映射Map.toSeq
, 管他呢。该序列的键是Google 返回的 JSON 结构 https://developers.google.com/+/web/api/rest/latest/people#resource对于“获取有关此人的更多详细信息”API 调用,值是这些键应在 ASP.NET 声明系统中映射到的声明类型。默认映射是use_google_oauth
已经做的是:
-
id
→ ClaimTypes.NameIdentifier
-
displayName
→ 声明类型.名称
-
emails[]
(参见注释)→ ClaimTypes.Email
这三个由 ASP.NET 自动映射。我添加了第四个映射:
-
avatar.url
→ `"urn:google:头像:url"
这个没有标准的 ClaimTypes 名称,所以我选择了一个任意的 URN。注意:此功能尚未发布,并且从现在到 Saturn 的下一版本中发布该功能,此字符串可能会发生变化(尽管不太可能)。
通过自动映射这四种声明类型,我发现不需要指定任何其他声明,因此我将最终参数留给use_google_oauth
作为我的演示应用程序中的空列表。但是如果您想要更多(假设您希望在本地化中使用用户的首选语言),那么只需将它们添加到该列表中,例如:
use_google_oauth googleClientId googleClientSecret "/oauth_callback_google" ["language", "urn:google:language"]
然后一旦有人登录,查看User.Claims
seq 用于类型声明"urn:google:language"
.
注意:emails[]
JSON 中的列表:我还没有使用具有多个电子邮件的 Google 帐户对此进行测试,因此我不知道 ASP.NET 如何选择电子邮件放入 ClaimTypes.Email 声明中。它可能只选择列表中的第一封电子邮件,也可能选择带有type
of account
;我只是不知道。可能需要一些实验。
另请注意,第三方 OAuth(包括 GitHub 和 Google)已拆分为新的 Saturn.Extensions.Authorization 包。它将在 Saturn 的下一个版本(可能是 0.7.0)发布的同时在 NuGet 上发布。
制作按钮
一旦你拥有了use_google_oauth
打电话给你的application
,创建如下内容:
let googleUserIdForRmunn = "106310971773596475579"
let matchUpUsers : HttpHandler = fun next ctx ->
// A real implementation would match up user identities with something stored in a database, not hardcoded in Users.fs like this example
let isRmunn =
ctx.User.Claims |> Seq.exists (fun claim ->
claim.Issuer = "Google" && claim.Type = ClaimTypes.NameIdentifier && claim.Value = googleUserIdForRmunn)
if isRmunn then
printfn "User rmunn is an admin of this demo app, adding admin role to user claims"
ctx.User.AddIdentity(new ClaimsIdentity([Claim(ClaimTypes.Role, "Admin", ClaimValueTypes.String, "MyApplication")]))
next ctx
let loggedIn = pipeline {
requires_authentication (Giraffe.Auth.challenge "Google")
plug matchUpUsers
}
let isAdmin = pipeline {
plug loggedIn
requires_role "Admin" (RequestErrors.forbidden (text "Must be admin"))
}
现在在你的范围内(注意:“范围”可能会在 Saturn 0.7.0 中重命名为“路由器”),执行如下操作:
let loggedInView = scope {
pipe_through loggedIn
get "/" (htmlView Index.layout)
get "/index.html" (redirectTo false "/")
get "/default.html" (redirectTo false "/")
get "/admin" (isAdmin >=> htmlView AdminPage.layout)
}
最后,让你的主路由器有一个 URL,将东西传递给loggedInView
router:
let browserRouter = scope {
not_found_handler (htmlView NotFound.layout) //Use the default 404 webpage
pipe_through browser //Use the default browser pipeline
forward "" defaultView //Use the default view
forward "/members-only" loggedInView
}
然后你的登录按钮就可以转到/members-only
路线,你会没事的。
请注意,如果您想要多个 OAuth 按钮(Google、GitHub、Facebook 等),您可能需要稍微调整一下,但这个答案已经足够长了。当您需要多个 OAuth 按钮时,请继续问另一个问题。