-
Notifications
You must be signed in to change notification settings - Fork 107
/
OAuth.fs
207 lines (174 loc) · 10 KB
/
OAuth.fs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
module Saturn
open System
open Microsoft.AspNetCore
open Microsoft.Extensions.DependencyInjection
open Microsoft.AspNetCore.Builder
open Microsoft.AspNetCore.Authentication
open Microsoft.AspNetCore.Authentication.Cookies
open Microsoft.AspNetCore.Authentication.Google
open Microsoft.AspNetCore.Authentication.OpenIdConnect
open Microsoft.AspNetCore.Http
open Saturn
let private addCookie state (c : AuthenticationBuilder) = if not state.CookiesAlreadyAdded then c.AddCookie() |> ignore
type Saturn.Application.ApplicationBuilder with
/// Enables default Google OAuth authentication.
/// `jsonToClaimMap` should contain a sequence of tuples where the first element is the name of the key in the JSON object and the second element is the name of the claim.
/// For example: `["id", ClaimTypes.NameIdentifier; "displayName", ClaimTypes.Name]` where `id` and `displayName` are names of fields in the Google JSON response (https://developers.google.com/+/web/api/rest/latest/people#resource).
[<CustomOperation("use_google_oauth")>]
member __.UseGoogleAuth(state: ApplicationState, clientId : string, clientSecret : string, callbackPath : string, jsonToClaimMap : (string * string) seq) =
let middleware (app : IApplicationBuilder) =
app.UseAuthentication()
let service (s : IServiceCollection) =
let c = s.AddAuthentication(fun cfg ->
cfg.DefaultScheme <- CookieAuthenticationDefaults.AuthenticationScheme
cfg.DefaultSignInScheme <- CookieAuthenticationDefaults.AuthenticationScheme
cfg.DefaultChallengeScheme <- "Google")
addCookie state c
c.AddGoogle(fun opt ->
opt.ClientId <- clientId
opt.ClientSecret <- clientSecret
opt.CallbackPath <- PathString(callbackPath)
jsonToClaimMap |> Seq.iter (fun (k,v) -> opt.ClaimActions.MapJsonKey(v,k) )
opt.ClaimActions.MapJsonSubKey("urn:google:image:url", "image", "url")
let ev = opt.Events
ev.OnCreatingTicket <- Func<_,_> Saturn.Application.parseAndValidateOauthTicket
) |> ignore
s
{ state with
ServicesConfig = service::state.ServicesConfig
AppConfigs = middleware::state.AppConfigs
CookiesAlreadyAdded = true
}
/// Enables Google OAuth authentication with custom configuration
[<CustomOperation("use_google_oauth_with_config")>]
member __.UseGoogleAuthWithConfig(state: ApplicationState, (config : Authentication.Google.GoogleOptions -> unit) ) =
let middleware (app : IApplicationBuilder) =
app.UseAuthentication()
let service (s : IServiceCollection) =
let c = s.AddAuthentication(fun cfg ->
cfg.DefaultScheme <- CookieAuthenticationDefaults.AuthenticationScheme
cfg.DefaultSignInScheme <- CookieAuthenticationDefaults.AuthenticationScheme
cfg.DefaultChallengeScheme <- "Google")
addCookie state c
c.AddGoogle(Action<GoogleOptions> config) |> ignore
s
{ state with
ServicesConfig = service::state.ServicesConfig
AppConfigs = middleware::state.AppConfigs
CookiesAlreadyAdded = true
}
/// Enables default GitHub OAuth authentication.
/// `jsonToClaimMap` should contain a sequence of tuples where the first element is the name of the key in the JSON object and the second element is the name of the claim.
/// For example: `["login", "githubUsername"; "name", "fullName"]` where `login` and `name` are names of fields in GitHub JSON response (https://developer.github.com/v3/users/#get-the-authenticated-user).
[<CustomOperation("use_github_oauth")>]
member __.UseGithubAuth(state: ApplicationState, clientId : string, clientSecret : string, callbackPath : string, jsonToClaimMap : (string * string) seq) =
let middleware (app : IApplicationBuilder) =
app.UseAuthentication()
let service (s : IServiceCollection) =
let c = s.AddAuthentication(fun cfg ->
cfg.DefaultScheme <- CookieAuthenticationDefaults.AuthenticationScheme
cfg.DefaultSignInScheme <- CookieAuthenticationDefaults.AuthenticationScheme
cfg.DefaultChallengeScheme <- "GitHub")
addCookie state c
c.AddOAuth("GitHub", fun (opt : Authentication.OAuth.OAuthOptions) ->
opt.ClientId <- clientId
opt.ClientSecret <- clientSecret
opt.CallbackPath <- PathString(callbackPath)
opt.AuthorizationEndpoint <- "https://github.com/login/oauth/authorize"
opt.TokenEndpoint <- "https://github.com/login/oauth/access_token"
opt.UserInformationEndpoint <- "https://api.github.com/user"
jsonToClaimMap |> Seq.iter (fun (k,v) -> opt.ClaimActions.MapJsonKey(v,k) )
let ev = opt.Events
ev.OnCreatingTicket <- Func<_,_> Saturn.Application.parseAndValidateOauthTicket
) |> ignore
s
{ state with
ServicesConfig = service::state.ServicesConfig
AppConfigs = middleware::state.AppConfigs
CookiesAlreadyAdded = true
}
/// Enables GitHub OAuth authentication with custom configuration
[<CustomOperation("use_github_oauth_with_config")>]
member __.UseGithubAuthWithConfig(state: ApplicationState, (config : Authentication.OAuth.OAuthOptions -> unit) ) =
let middleware (app : IApplicationBuilder) =
app.UseAuthentication()
let service (s : IServiceCollection) =
let c = s.AddAuthentication(fun cfg ->
cfg.DefaultScheme <- CookieAuthenticationDefaults.AuthenticationScheme
cfg.DefaultSignInScheme <- CookieAuthenticationDefaults.AuthenticationScheme
cfg.DefaultChallengeScheme <- "GitHub")
addCookie state c
c.AddOAuth("GitHub",config) |> ignore
s
{ state with
ServicesConfig = service::state.ServicesConfig
AppConfigs = middleware::state.AppConfigs
CookiesAlreadyAdded = true
}
/// Enalbes default Azure AD OAuth authentication.
/// `scopes` must be at least on of the scopes defined in https://docs.microsoft.com/en-us/graph/permissions-reference, for instance "User.Read".
/// `jsonToClaimMap` should contain a sequence of tuples where the first element is the name of the key in the JSON object and the second element is the name of the claim.
/// For example: `["name", "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name" ]` where `name` is the names of a field in Azure AD's JSON response (see https://docs.microsoft.com/en-us/azure/active-directory/develop/id-tokens or inspect tokens with https://jwt.ms).
[<CustomOperation("use_azuread_oauth")>]
member __.UseAzureADAuth(state: ApplicationState, tenantId : string, clientId : string, clientSecret: string, callbackPath : string, scopes : string seq, jsonToClaimMap : (string * string) seq) =
let middleware (app : IApplicationBuilder) =
app.UseAuthentication()
let service (s : IServiceCollection) =
let c = s.AddAuthentication(fun cfg ->
cfg.DefaultScheme <- CookieAuthenticationDefaults.AuthenticationScheme
cfg.DefaultSignInScheme <- CookieAuthenticationDefaults.AuthenticationScheme
cfg.DefaultChallengeScheme <- "AzureAD")
addCookie state c
c.AddOAuth("AzureAD", fun (opt : Authentication.OAuth.OAuthOptions) ->
opt.ClientId <- clientId
opt.ClientSecret <- clientSecret
opt.CallbackPath <- PathString(callbackPath)
opt.AuthorizationEndpoint <- sprintf "https://login.microsoftonline.com/%s/oauth2/v2.0/authorize" tenantId
opt.TokenEndpoint <- sprintf "https://login.microsoftonline.com/%s/oauth2/v2.0/token" tenantId
opt.UserInformationEndpoint <- "https://graph.microsoft.com/oidc/userinfo"
jsonToClaimMap |> Seq.iter (fun (k,v) -> opt.ClaimActions.MapJsonKey(v,k) )
scopes |> Seq.iter (opt.Scope.Add)
let ev = opt.Events
ev.OnCreatingTicket <- Func<_,_> Saturn.Application.parseAndValidateOauthTicket
) |> ignore
s
{ state with
ServicesConfig = service::state.ServicesConfig
AppConfigs = middleware::state.AppConfigs
CookiesAlreadyAdded = true
}
/// Enables AzureAD OAuth authentication with custom configuration
[<CustomOperation("use_azuread_oauth_with_config")>]
member __.UseAzureADAuthWithConfig(state: ApplicationState, (config : Authentication.OAuth.OAuthOptions -> unit) ) =
let middleware (app : IApplicationBuilder) =
app.UseAuthentication()
let service (s : IServiceCollection) =
let c = s.AddAuthentication(fun cfg ->
cfg.DefaultScheme <- CookieAuthenticationDefaults.AuthenticationScheme
cfg.DefaultSignInScheme <- CookieAuthenticationDefaults.AuthenticationScheme
cfg.DefaultChallengeScheme <- "AzureAD")
addCookie state c
c.AddOAuth("AzureAD",config) |> ignore
s
{ state with
ServicesConfig = service::state.ServicesConfig
AppConfigs = middleware::state.AppConfigs
CookiesAlreadyAdded = true
}
/// Enables OpenId authentication with custom configuration
[<CustomOperation("use_open_id_auth_with_config")>]
member __.UseOpenIdAuthWithConfig(state: ApplicationState, (config: Action<OpenIdConnect.OpenIdConnectOptions>)) =
let middleware (app : IApplicationBuilder) =
app.UseAuthentication()
let service (s: IServiceCollection) =
let authBuilder = s.AddAuthentication(fun authConfig ->
authConfig.DefaultScheme <- CookieAuthenticationDefaults.AuthenticationScheme
authConfig.DefaultChallengeScheme <- OpenIdConnectDefaults.AuthenticationScheme
authConfig.DefaultSignInScheme <- CookieAuthenticationDefaults.AuthenticationScheme)
addCookie state authBuilder
authBuilder.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, config) |> ignore
s
{ state with
ServicesConfig = service::state.ServicesConfig
AppConfigs = middleware::state.AppConfigs
CookiesAlreadyAdded = true }