| | | 1 | | using System.Diagnostics; |
| | | 2 | | using Elsa.ExternalAuthentication.Models; |
| | | 3 | | |
| | | 4 | | namespace Elsa.ExternalAuthentication.Services; |
| | | 5 | | |
| | | 6 | | /// <summary> |
| | | 7 | | /// Produces the deliberately small, non-sensitive error contract exposed by the authentication broker. |
| | | 8 | | /// </summary> |
| | | 9 | | public static class BrokerErrorFactory |
| | | 10 | | { |
| | | 11 | | public static PublicBrokerError Create(BrokerErrorCategory category, string? correlationId = null) |
| | | 12 | | { |
| | 37 | 13 | | var (error, message) = category switch |
| | 37 | 14 | | { |
| | 14 | 15 | | BrokerErrorCategory.InvalidRequest => ("invalid_request", "The sign-in request is invalid. Start again."), |
| | 5 | 16 | | BrokerErrorCategory.MethodUnavailable => ("method_unavailable", "This sign-in method is unavailable."), |
| | 6 | 17 | | BrokerErrorCategory.AuthenticationFailed => ("authentication_failed", "Authentication could not be completed |
| | 1 | 18 | | BrokerErrorCategory.IdentityUnlinked => ("identity_unlinked", "This identity is not permitted to sign in."), |
| | 1 | 19 | | BrokerErrorCategory.FlowExpired => ("flow_expired", "The sign-in attempt expired. Start again."), |
| | 3 | 20 | | BrokerErrorCategory.FlowChanged => ("flow_changed", "The sign-in method changed. Start again."), |
| | 1 | 21 | | BrokerErrorCategory.AccessDenied => ("access_denied", "Access was denied."), |
| | 1 | 22 | | BrokerErrorCategory.RateLimited => ("rate_limited", "Too many sign-in attempts. Try again later."), |
| | 3 | 23 | | BrokerErrorCategory.TemporarilyUnavailable => ("temporarily_unavailable", "Sign-in is temporarily unavailabl |
| | 2 | 24 | | BrokerErrorCategory.ServerError => ("server_error", "Sign-in could not be completed. Try again later."), |
| | 0 | 25 | | _ => throw new ArgumentOutOfRangeException(nameof(category), category, null) |
| | 37 | 26 | | }; |
| | | 27 | | |
| | 37 | 28 | | return new PublicBrokerError(error, message, IsSafeCorrelationId(correlationId) ? correlationId! : CreateCorrela |
| | | 29 | | } |
| | | 30 | | |
| | | 31 | | public static string CreateCorrelationId() |
| | | 32 | | { |
| | 50 | 33 | | var traceId = Activity.Current?.TraceId.ToString(); |
| | 50 | 34 | | return !string.IsNullOrWhiteSpace(traceId) && traceId != "00000000000000000000000000000000" |
| | 50 | 35 | | ? traceId |
| | 50 | 36 | | : ActivityTraceId.CreateRandom().ToString(); |
| | | 37 | | } |
| | | 38 | | |
| | | 39 | | private static bool IsSafeCorrelationId(string? correlationId) |
| | | 40 | | { |
| | 37 | 41 | | if (string.IsNullOrWhiteSpace(correlationId) || correlationId.Length > 128) |
| | 25 | 42 | | return false; |
| | | 43 | | |
| | 247 | 44 | | return correlationId.All(character => char.IsAsciiLetterOrDigit(character) || character is '-' or '_'); |
| | | 45 | | } |
| | | 46 | | } |