Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
OAuthAuthorizeResource.cs
1using System;
3using System.Text;
4using System.Threading.Tasks;
5using System.Web;
6using Waher.Content;
10using Waher.Events;
17using Waher.Script;
21
23{
29 {
33 public const string DefaultResourcePath = "/oauth/authorize";
34
41 {
42 }
43
51 {
53 }
54
58 public bool AllowsGET => true;
59
63 public bool AllowsPOST => true;
64
71 public async Task GET(HttpRequest Request, HttpResponse Response)
72 {
73 if (HasDuplicateQueryParameters(Request))
74 {
75 await BadRequest(Response, "invalid_request",
76 "Duplicate query parameters.");
77 return;
78 }
79
80 if (!Request.Header.TryGetQueryParameter("response_type", out string ResponseType))
81 {
82 await BadRequest(Response, "invalid_request",
83 "Missing response_type parameter.");
84 return;
85 }
86
87 await this.PrepareForm(ResponseType, Request.Header.QueryParametersPerName,
88 Request, Response);
89 }
90
91 internal static bool HasDuplicateQueryParameters(HttpRequest Request)
92 {
93 HashSet<string> Parameters = new HashSet<string>();
94
95 foreach (KeyValuePair<string, string> P in Request.Header.QueryParameters)
96 {
97 if (Parameters.Contains(P.Key))
98 return true;
99 else
100 Parameters.Add(P.Key);
101 }
102
103 return false;
104 }
105
106 private async Task PrepareForm(string ResponseType, IDictionary<string, string> Form,
107 HttpRequest Request, HttpResponse Response)
108 {
109 if (!Form.TryGetValue("state", out string State))
110 State = string.Empty;
111
112 if (!Form.TryGetValue("scope", out string Scope))
113 Scope = string.Empty;
114 else if (!IsValidScope(Scope))
115 {
116 await BadRequest(Response, "invalid_scope", "Invalid scope parameter.");
117 return;
118 }
119
120 switch (ResponseType)
121 {
122 case "code": // Authorization Code
123 if (!Form.TryGetValue("client_id", out string ClientId))
124 ClientId = string.Empty;
125
126 if (!Form.TryGetValue("redirect_uri", out string RedirectUri) ||
127 string.IsNullOrEmpty(RedirectUri))
128 {
129 await BadRequest(Response, "invalid_request",
130 "Missing or empty redirect_uri parameter.");
131 return;
132 }
133
134 if (!Uri.TryCreate(RedirectUri, UriKind.Absolute, out Uri? RedirectUri2))
135 {
136 await BadRequest(Response, "invalid_redirect_uri",
137 "Invalid redirection URI.");
138 return;
139 }
140
141 if (!RedirectUri.StartsWith("https://") && RedirectUri2.Host != "localhost")
142 {
143 await BadRequest(Response, "invalid_request",
144 "Callback URIs must use HTTPS URI scheme (unless localhost) to ensure secure communication.");
145 return;
146 }
147
148 if (!Form.TryGetValue("code_challenge", out string CodeChallenge))
149 CodeChallenge = string.Empty;
150
151 if (!Form.TryGetValue("code_challenge_method", out string CodeChallengeMethod) ||
152 string.IsNullOrEmpty(CodeChallengeMethod))
153 {
154 CodeChallengeMethod = "plain";
155 }
156
157 if (CodeChallengeMethod != "plain" && CodeChallengeMethod != "S256")
158 {
159 await BadRequest(Response, "invalid_request",
160 "Unsupported code_challenge_method: " + CodeChallengeMethod);
161 return;
162 }
163
164 Response.SetHeader("Cache-Control", "max-age=0, no-cache, no-store");
165 Response.SetHeader("Pragma", "no-cache");
166
167 await Response.Return(await this.GenerateLoginForm(Response, ClientId,
168 RedirectUri, State, Scope, CodeChallenge, CodeChallengeMethod,
169 string.Empty, RedirectUri));
170 return;
171
172 case "token": // Implicit
174 await this.ImplicitAuthenticationRequest.Raise(this, e);
175
177
178 if (User is null &&
180 Request.User is IUserWithClaims UserWithClaims)
181 {
182 User = UserWithClaims;
183 }
184
185 if (!(User is null))
186 {
187 if (Form.TryGetValue("client_id", out ClientId) &&
188 ClientId != User.UserName)
189 {
190 LoginAuditor.Fail("Credentials mismatch. User name in request: " +
191 ClientId + ", user name in authenticated user: " + User.UserName,
192 User.UserName, Request.RemoteEndPoint, "OAUTH");
193
194 await Forbidden(Response, "invalid_request", "Invalid credentials.");
195 return;
196 }
197
198 if (!HasScopePrivileges(Scope, User, out string? MissingPrivilege))
199 {
200 await Forbidden(Response, "access_denied",
201 "User lacks privilege: " + MissingPrivilege);
202 return;
203 }
204
205 Response.SetHeader("Cache-Control", "max-age=0, no-cache, no-store");
206 Response.SetHeader("Pragma", "no-cache");
207
208 string Token = await OAuthTokenResource.CreateToken(User,
209 Request.Encrypted, this.JwtFactory, Scope);
210
211 await Response.Return(this.Environment.TokenResource.TokenResponse(Token, State,
212 3600, Scope, this.JwtFactory.Issuer, false, User, Request));
213 return;
214 }
215
216 if (!this.InitAuthentication())
217 {
218 await ServiceUnavailable(Response, "server_error",
219 "Authentication not enabled.");
220 }
221 else
222 {
223 ChunkedList<string>? Challenges = null;
224
225 foreach (HttpAuthenticationScheme AuthenticationScheme in this.AuthenticationSchemes!)
226 {
227 if (AuthenticationScheme is MutualTlsAuthentication)
228 {
230 continue;
231 }
232 else
233 {
235 continue;
236 }
237
238 Challenges ??= new ChunkedList<string>();
239 Challenges.AddRange(AuthenticationScheme.GetChallenges(Request));
240 }
241
242 if (Challenges is null)
243 await Forbidden(Response, "access_denied", "Access denied");
244 else
245 {
246 await Unauthorized(Response, "access_denied", "Access denied",
247 Challenges.ToArray());
248 }
249 }
250 return;
251
252 default:
253 if (string.IsNullOrEmpty(ResponseType))
254 {
255 await BadRequest(Response, "invalid_request",
256 "Empty response_type.");
257 return;
258 }
259 else
260 {
261 await BadRequest(Response, "unsupported_response_type",
262 "Unsupported response_type parameter: " + ResponseType);
263 }
264 return;
265 }
266 }
267
271 public event EventHandlerAsync<ImplicitAuthenticationEventArgs>? ImplicitAuthenticationRequest = null;
272
273 private async Task<HtmlDocument> GenerateLoginForm(HttpResponse Response,
274 string UserName, string From, string State, string Scope, string CodeChallenge,
275 string CodeChallengeMethod, string ErrorMessage, string RedirectUri)
276 {
277 StringBuilder Markdown = new StringBuilder();
278
279 Markdown.AppendLine("Title: Login");
280 Markdown.AppendLine("Description: OAUTH login page.");
281
283 {
284 Markdown.Append("Master: ");
285 Markdown.AppendLine(this.Environment.LoginMasterFileName);
286 }
287
288 Markdown.Append("Date: ");
289 Markdown.AppendLine(CommonTypes.EncodeRfc822(DateTime.UtcNow));
290 Markdown.AppendLine();
291 Markdown.AppendLine(new string('=', 40));
292 Markdown.AppendLine();
293
294 Markdown.AppendLine("Login");
295 Markdown.AppendLine("========");
296 Markdown.AppendLine();
297
298 int i = RedirectUri.IndexOf("://");
299 string? Host = null;
300 string? Origin = null;
301
302 if (i > 0)
303 {
304 int j = RedirectUri.IndexOf('/', i + 3);
305 if (j > i)
306 {
307 Host = RedirectUri.Substring(i + 3, j - i - 3);
308 Origin = RedirectUri[..j];
309 }
310 }
311
312 i = RedirectUri.IndexOf('?');
313 OAuthRedirectUri? RegisteredUri = await Database.FindFirstIgnoreRest<OAuthRedirectUri>(
314 new FilterFieldEqualTo("Uri", i > 0 ? RedirectUri[..i] : RedirectUri));
315 OAuthClientInformation? ClientInfo = RegisteredUri is null ? null :
316 await Database.FindFirstIgnoreRest<OAuthClientInformation>(
317 new FilterFieldEqualTo("ClientId", RegisteredUri.ClientId));
318
319 if (!(ClientInfo is null))
320 {
321 if (!string.IsNullOrEmpty(ClientInfo.LogoUri))
322 {
323 Markdown.Append("![](");
324 Markdown.Append(ClientInfo.LogoUri);
325 Markdown.AppendLine(")");
326 }
327
328 Markdown.AppendLine();
329
330 if (!string.IsNullOrEmpty(ClientInfo.ClientName))
331 {
332 if (!string.IsNullOrEmpty(ClientInfo.ClientUri))
333 {
334 Markdown.Append("You have been requested to log in by [*");
335 Markdown.Append(ClientInfo.ClientName);
336 Markdown.Append("*](");
337 Markdown.Append(ClientInfo.ClientUri);
338 Markdown.Append("). ");
339 }
340 else
341 {
342 Markdown.Append("You have been requested to log in by *");
343 Markdown.Append(ClientInfo.ClientName);
344 Markdown.Append("*. ");
345 }
346 }
347 else
348 {
349 }
350 }
351 else if (!string.IsNullOrEmpty(Host))
352 {
353 Markdown.Append("You have been requested to log in by an **unregistered** ");
354 Markdown.Append("remote service at `");
355 Markdown.Append(Host);
356 Markdown.Append("`. ");
357 }
358 else
359 {
360 Markdown.Append("You have been requested to log in to an **unregistered** ");
361 Markdown.Append("remote service. ");
362 }
363
364 Markdown.Append("If you trust this service, please log in below. ");
365 Markdown.AppendLine("Otherwise, close the window and ignore the request.");
366 Markdown.AppendLine();
367
368 string ParametersToken = this.JwtFactory.Create(
369 new KeyValuePair<string, object>("redirect_uri", From),
370 new KeyValuePair<string, object>("state", State),
371 new KeyValuePair<string, object>("scope", Scope),
372 new KeyValuePair<string, object>("code_challenge", CodeChallenge),
373 new KeyValuePair<string, object>("code_challenge_method", CodeChallengeMethod));
374
375 Markdown.Append("<form id='LoginForm' action='");
376 Markdown.Append(this.ResourceName);
377 Markdown.Append("' method='post'>");
378 Markdown.Append("<input type='hidden' name='p' value='");
379 Markdown.Append(XML.HtmlAttributeEncode(ParametersToken));
380 Markdown.AppendLine("'/>");
381 Markdown.AppendLine();
382
383 Markdown.AppendLine("<p>");
384 Markdown.AppendLine("<label for='client_id'>User Name:</label> ");
385 Markdown.Append("<input id='client_id' name='client_id' type='text' autofocus autocomplete='username");
386
387 if (!string.IsNullOrEmpty(UserName))
388 {
389 Markdown.Append("' value='");
390 Markdown.Append(XML.HtmlAttributeEncode(UserName));
391 }
392
393 Markdown.AppendLine("'/>");
394 Markdown.AppendLine("</p>");
395 Markdown.AppendLine();
396
397 Markdown.AppendLine("<p>");
398 Markdown.AppendLine("<label for='client_secret'>Password:</label> ");
399 Markdown.Append("<input id='client_secret' name='client_secret' type='password' ");
400 Markdown.AppendLine("autocomplete='current-password'/>");
401 Markdown.AppendLine("</p>");
402 Markdown.AppendLine();
403
404 if (!string.IsNullOrEmpty(ErrorMessage))
405 {
406 Markdown.AppendLine("<p>");
407 Markdown.Append("<strong id='errorMessage'>");
408 Markdown.Append(XML.HtmlValueEncode(ErrorMessage));
409 Markdown.AppendLine("</strong>");
410 Markdown.AppendLine("</p>");
411 Markdown.AppendLine();
412 }
413
414 Markdown.AppendLine("<button type='submit'>Login</button>");
415 Markdown.AppendLine("</form>");
416 Markdown.AppendLine();
417
418 if (!string.IsNullOrEmpty(ClientInfo?.TosUri))
419 {
420 Markdown.Append("[Terms of Service](");
421 Markdown.Append(ClientInfo.TosUri);
422 Markdown.AppendLine(")");
423 }
424
425 if (!string.IsNullOrEmpty(ClientInfo?.PolicyUri))
426 {
427 Markdown.Append("[Privacy Policy](");
428 Markdown.Append(ClientInfo.PolicyUri);
429 Markdown.AppendLine(")");
430 }
431
432 if ((ClientInfo?.Contacts?.Length ?? 0) > 0)
433 {
434 foreach (string Contact in ClientInfo?.Contacts ?? Array.Empty<string>())
435 {
436 if (!string.IsNullOrEmpty(Contact))
437 {
438 Markdown.Append("[Contact](");
439
440 if (Contact.IndexOf(':') < 0)
441 {
442 if (Contact.Contains('@'))
443 Markdown.Append("mailto:");
444 else
445 Markdown.Append("tel:");
446 }
447
448 Markdown.Append(Contact);
449 Markdown.AppendLine(")");
450 }
451 }
452 }
453
454 string Markdown2 = await this.Environment.RaiseCustomizeLoginForm(Markdown.ToString());
455
456 MarkdownDocument Doc = await MarkdownDocument.CreateAsync(Markdown2,
457 new MarkdownSettings()
458 {
459 Variables = new Variables()
460 });
461
462 string Html = await Doc.GenerateHTML();
463
464 Response.SetHeader("X-Frame-Options", "DENY");
465 Response.SetHeader("Content-Security-Policy", "frame-ancestors 'none'; " +
466 "default-src 'self'; script-src 'self'; object-src 'none'; " +
467 "base-uri 'none'; form-action 'self'" +
468 (string.IsNullOrEmpty(Origin) ? string.Empty : " " + Origin));
469
470 return new HtmlDocument(Html);
471 }
472
479 public async Task POST(HttpRequest Request, HttpResponse Response)
480 {
481 if (!Request.HasData)
482 {
483 await BadRequest(Response, "invalid_request", "Missing payload.");
484 return;
485 }
486
487 ContentResponse Content = await Request.DecodeDataAsync();
488 if (Content.HasError || !(Content.Decoded is Dictionary<string, string> Form))
489 {
490 await BadRequest(Response, "invalid_request",
491 "Expected URL-encoded WWW form.");
492 return;
493 }
494
495 if (Form.TryGetValue("response_type", out string ResponseType))
496 {
497 await this.PrepareForm(ResponseType, Form, Request, Response);
498 return;
499 }
500
501 if (!Form.TryGetValue("client_id", out string UserName) ||
502 !Form.TryGetValue("client_secret", out string Password) ||
503 !Form.TryGetValue("p", out string ParametersToken) ||
504 string.IsNullOrEmpty(ParametersToken) ||
505 !JwtToken.TryParse(ParametersToken, out JwtToken? Parameters) ||
506 !this.JwtFactory.IsValid(Parameters) ||
507 !Parameters.TryGetClaim("redirect_uri", out object Obj) || !(Obj is string RedirectUri) ||
508 !Parameters.TryGetClaim("state", out Obj) || !(Obj is string State) ||
509 !Parameters.TryGetClaim("scope", out Obj) || !(Obj is string Scope) ||
510 !Parameters.TryGetClaim("code_challenge", out Obj) || !(Obj is string CodeChallenge))
511 {
512 await BadRequest(Response, "invalid_request", "Invalid form.");
513 return;
514 }
515
516 if (!Parameters.TryGetClaim("code_challenge_method", out Obj) ||
517 !(Obj is string CodeChallengeMethod) ||
518 string.IsNullOrWhiteSpace(CodeChallengeMethod))
519 {
520 CodeChallengeMethod = "plain";
521 }
522
523 if (CodeChallengeMethod != "plain" && CodeChallengeMethod != "S256")
524 {
525 await BadRequest(Response, "invalid_request",
526 "Unsupported code_challenge_method: " + CodeChallengeMethod);
527 return;
528 }
529
530 if (string.IsNullOrEmpty(RedirectUri))
531 {
532 await BadRequest(Response, "invalid_request",
533 "Missing or empty redirect_uri parameter.");
534 return;
535 }
536
537 this.InitAuthentication();
538
539 LoginResult? LoginResult = await OAuthTokenResource.DoLogin(UserName, Password,
540 this.Users!, Request, this.Realm ?? string.Empty);
541
542 if (LoginResult is null)
543 {
544 await Forbidden(Response, "access_denied",
545 "User cannot authenticate via this interface.");
546 return;
547 }
548
549 switch (LoginResult.Type)
550 {
551 case LoginResultType.Success:
552 Request.User = LoginResult.User;
553
554 if (!(LoginResult.User is IUserWithClaims UserWithClaims))
555 {
556 await Response.Return(await this.GenerateLoginForm(Response,
557 UserName, RedirectUri, State, Scope, CodeChallenge,
558 CodeChallengeMethod, "User cannot be used with OAUTH login.",
559 RedirectUri));
560 return;
561 }
562
563 if (!string.IsNullOrEmpty(Scope) &&
564 !HasScopePrivileges(Scope, LoginResult.User, out string? _))
565 {
566 await Response.Return(await this.GenerateLoginForm(Response,
567 UserName, RedirectUri, State, Scope, CodeChallenge,
568 CodeChallengeMethod, "User does not have sufficient privileges to complete the request.",
569 RedirectUri));
570 return;
571 }
572
573 string Code = await this.Environment.TokenResource.GenerateTokenCode(UserWithClaims,
574 Request.Encrypted, CodeChallenge, CodeChallengeMethod, RedirectUri,
575 Scope);
576
577 if (RedirectUri.Contains('?'))
578 RedirectUri += "&code=" + HttpUtility.UrlEncode(Code);
579 else
580 RedirectUri += "?code=" + HttpUtility.UrlEncode(Code);
581
582 if (!string.IsNullOrEmpty(State))
583 RedirectUri += "&state=" + HttpUtility.UrlEncode(State);
584
585 if (this.JwtFactory.HasIssuer)
586 RedirectUri += "&iss=" + HttpUtility.UrlEncode(this.JwtFactory.Issuer);
587
588 await Response.SendResponse(new SeeOtherException(RedirectUri));
589 break;
590
591 case LoginResultType.InvalidCredentials:
592 default:
593 await Response.Return(await this.GenerateLoginForm(Response, UserName,
594 RedirectUri, State, Scope, CodeChallenge, CodeChallengeMethod,
595 "Invalid user name or password.", RedirectUri));
596 return;
597
598 case LoginResultType.NoPassword:
599 await Forbidden(Response, "access_denied", "Password empty.");
600 return;
601
602 case LoginResultType.TemporarilyBlocked:
603 await Response.Return(await this.GenerateLoginForm(Response, UserName,
604 RedirectUri, State, Scope, CodeChallenge, CodeChallengeMethod,
605 "You are temporarily blocked. Try again after: " +
606 LoginResult.Next?.ToString(), RedirectUri));
607 return;
608
609 case LoginResultType.PermanentlyBlocked:
610 await Response.Return(await this.GenerateLoginForm(Response, UserName,
611 RedirectUri, State, Scope, CodeChallenge, CodeChallengeMethod,
612 "You are permanently blocked.", RedirectUri));
613 return;
614 }
615 }
616
617 }
618}
Helps with parsing of commong data types.
Definition: CommonTypes.cs:15
static string EncodeRfc822(DateTime Timestamp)
Encodes a date and time, according to RFC 822 §5.
Definition: CommonTypes.cs:669
Contains information about a response to a content request.
bool HasError
If an error occurred.
object Decoded
Decoded object.
Contains a markdown document. This markdown document class supports original markdown,...
async Task< string > GenerateHTML()
Generates HTML from the markdown text.
static Task< MarkdownDocument > CreateAsync(string MarkdownText, params Type[] TransparentExceptionTypes)
Contains a markdown document. This markdown document class supports original markdown,...
Contains settings that the Markdown parser uses to customize its behavior.
Helps with common XML-related tasks.
Definition: XML.cs:21
static string HtmlValueEncode(string s)
Differs from Encode(String), in that it does not encode the aposotrophe or the quote.
Definition: XML.cs:211
static string HtmlAttributeEncode(string s)
Differs from Encode(String), in that it does not encode the aposotrophe.
Definition: XML.cs:121
mTLS authentication mechanism, where identity is taken from a valid client certificate.
Base class for all HTTP authentication schemes, as defined in RFC-7235: https://datatracker....
abstract string[] GetChallenges(HttpRequest Request)
Gets available challenges for the authenticating client to respond to.
KeyValuePair< string, string >[] QueryParameters
All query parameters.
IDictionary< string, string > QueryParametersPerName
Query parameters per name. If multiple query parameters with the same name are present,...
bool TryGetQueryParameter(string QueryParameter, out string Value)
Tries to get the value of an individual query parameter, if available.
Represents an HTTP request.
Definition: HttpRequest.cs:22
HttpRequestHeader Header
Request header.
Definition: HttpRequest.cs:182
string RemoteEndPoint
Remote end-point.
Definition: HttpRequest.cs:243
bool HasData
If the request has data.
Definition: HttpRequest.cs:113
bool Encrypted
If the connection is encrypted or not.
Definition: HttpRequest.cs:298
IUser User
Authenticated user, if available, or null if not available.
Definition: HttpRequest.cs:203
async Task< ContentResponse > DecodeDataAsync()
Decodes data sent in request.
Definition: HttpRequest.cs:139
string ResourceName
Name of resource.
Represets a response of an HTTP client request.
Definition: HttpResponse.cs:23
async Task SendResponse()
Sends the response back to the client. If the resource is synchronous, there's no need to call this m...
void SetHeader(string FieldName, string Value)
Sets a custom header field value.
Task Return(Exception ex)
Returns an error to the client.
Contains information about an OAuth client, as defined in RFC 7591.
Contains information about a redirect URI using by an OAuth client.
string ClientId
OAuth 2.0 client identifier string.
Event arguments for implicit OAUTH authentication requests.
bool PermitMtlsAuthentication
If user identity can be implicitly authenticated using the client certificate used in mutual TLS auth...
IUserWithClaims? User
Implicitly authenticated user, if any. If null, no user was authenticated.
bool PermitWwwAuthentication
If implicit authentication can use result of WWW-Authenticate mechanism in HTTP to identify a user,...
OAuthTokenResource TokenResource
Registered token resource
void Register(OAuthAuthorizeResource? AuthorizeResource)
Registers an authorization resource.
string? LoginMasterFileName
File name to master file to use in generated login pages.
bool HasLoginMasterFileName
If a login master file name has been registered
async Task< string > RaiseCustomizeLoginForm(string Markdown)
Raises the CustomizeLoginForm event to customize a login form before being returned to the client.
OAUTH authorize resource, as defined in RFC 6749. https://datatracker.ietf.org/doc/html/rfc6749
const string DefaultResourcePath
Default authorize resource path: /oauth/authorize
EventHandlerAsync< ImplicitAuthenticationEventArgs >? ImplicitAuthenticationRequest
Event raised when an implicit authentication request is received.
OAuthAuthorizeResource(OAuth2Environment Environment)
OAUTH authorize resource, as defined in RFC 6749.
async Task POST(HttpRequest Request, HttpResponse Response)
Executes the POST method on the resource.
async Task GET(HttpRequest Request, HttpResponse Response)
Executes the GET method on the resource.
OAuthAuthorizeResource(OAuth2Environment Environment, string ResourceName)
OAUTH authorize resource, as defined in RFC 6749.
Abstract base class for OAUTH resources.
OAuth2Environment Environment
OAUTH2 environment, used to access clients, tokens, and other resources.
string? Realm
Realm name, if any, used for authentication. Null if no realm is defined.
static Task ServiceUnavailable(HttpResponse Response, string ErrorCode, string ErrorDescription)
Returns a Service Unavailable error back to the client.
static bool IsValidScope(string Scope)
Checks if a scope value is valid, according to the OAUTH2 specification.
bool InitAuthentication()
Initializes authentication schemes, if not already initialized.
static Task BadRequest(HttpResponse Response, string ErrorCode, string ErrorDescription)
Returns a Bad Request error back to the client.
static Task Unauthorized(HttpResponse Response, string ErrorCode, string ErrorDescription, string[] Challenges)
Returns an Unauthorized error back to the client.
static Task Forbidden(HttpResponse Response, string ErrorCode, string ErrorDescription)
Returns a Forbidden error back to the client.
static bool HasScopePrivileges(string Scopes, IUser User, [NotNullWhen(false)] out string? MissingPrivilege)
Checks if a user has the privileges associated with a set of scopes.
HttpAuthenticationScheme?[] AuthenticationSchemes
Available authentication schemes, if initialized.
OAUTH token resource, as defined in RFC 6749. https://datatracker.ietf.org/doc/html/rfc6749
The response to the request can be found under a different URI and SHOULD be retrieved using a GET me...
Static interface for database persistence. In order to work, a database provider has to be assigned t...
Definition: Database.cs:21
This filter selects objects that have a named field equal to a given value.
A chunked list is a linked list of chunks of objects of type T .
Definition: ChunkedList.cs:54
void AddRange(IEnumerable< T > Collection)
Adds a range of elements (last) to the list.
T[] ToArray()
Returns an array containing all elements of the collection.
Collection of variables.
Definition: Variables.cs:25
A factory that can create and validate JWT tokens.
Definition: JwtFactory.cs:66
bool HasIssuer
If the factory has an issuer identifier.
Definition: JwtFactory.cs:258
string Issuer
Issuer identifier of the token factory, if available.
Definition: JwtFactory.cs:253
string Create(params KeyValuePair< string, object >[] Claims)
Creates a new JWT token.
Definition: JwtFactory.cs:379
Contains information about a Java Web Token (JWT). JWT is defined in RFC 7519: https://tools....
Definition: JwtToken.cs:22
static bool TryParse(string Token, out JwtToken ParsedToken)
Tries to parse a JWT token.
Definition: JwtToken.cs:68
Class that monitors login events, and help applications determine malicious intent....
Definition: LoginAuditor.cs:26
static void Fail(string Message, string UserName, string RemoteEndPoint, string Protocol)
Handles a failed login attempt.
Contains information about a login attempt.
Definition: LoginResult.cs:40
IUser User
User object corresponding to the successfully logged in user.
Definition: LoginResult.cs:80
DateTime? Next
Time when a new login can be attempted.
Definition: LoginResult.cs:85
LoginResultType Type
Type of login result.
Definition: LoginResult.cs:90
Corresponds to a user in the system.
Definition: User.cs:24
string UserName
User Name
Definition: User.cs:60
Maintains the collection of all users in the system.
Definition: Users.cs:24
GET Interface for HTTP resources.
POST Interface for HTTP resources.
A User that can participate in distributed operations, where the user is identified using a JWT token...
Definition: ImplTypes.g.cs:58
LoginResultType
Result of login attempt
Definition: LoginResult.cs:9