Beispiel #1
0
        /// <summary>
        /// This method handles the routing of a request that the middleware is working with to the correct logic
        /// </summary>
        /// <returns>Handle which indicates that the request has been responded to or Success if the user has been logged in</returns>
        protected override Task <HandleRequestResult> HandleRemoteAuthenticateAsync()
        {
            Logger.LogTrace("Started working on request");

            CommandWorker.Request  = Request;
            CommandWorker.Response = Response;
            CommandWorker.Options  = Options;     //Options will probably never change but to make sure the static object is up to date lets set it

            if (Request.Query.ContainsKey("nut")) //Generally requests from a SQRL client
            {
                Logger.LogInformation("Processing nut request");
                CommandWorker.NutRequest();
            }
            else if (Request.Query.ContainsKey("check")) //Helper for initial page to check when a user has logged in
            {
                Logger.LogInformation("Processing check request");
                return(CheckRequest());
            }
            else if (Request.Query.ContainsKey("cps"))
            {
                Logger.LogInformation("Processing cps request");
                return(CheckCpsRequest());
            }
            else if (Request.Query.ContainsKey("diag") && Options.Diagnostics)
            {
                Logger.LogInformation("Processing diag request");
                return(DiagnosticsPage());
            }
            else if (Request.Query.ContainsKey("helper"))
            {
                Logger.LogInformation("Processing helper request");
                CommandWorker.HelperJson();
            }
            else if (!Options.DisableDefaultLoginPage) //For everything else we should only return a login page
            {
                Logger.LogInformation("Processing default login page request");
                CommandWorker.QrCodePage();
            }

            Logger.LogTrace("Finished working on request");
            return(Task.FromResult(HandleRequestResult.Handle()));
        }
    /// <summary>
    /// Derived types may override this method to handle access denied errors.
    /// </summary>
    /// <param name="properties">The <see cref="AuthenticationProperties"/>.</param>
    /// <returns>The <see cref="HandleRequestResult"/>.</returns>
    protected virtual async Task <HandleRequestResult> HandleAccessDeniedErrorAsync(AuthenticationProperties properties)
    {
        Logger.AccessDeniedError();
        var context = new AccessDeniedContext(Context, Scheme, Options)
        {
            AccessDeniedPath   = Options.AccessDeniedPath,
            Properties         = properties,
            ReturnUrl          = properties?.RedirectUri,
            ReturnUrlParameter = Options.ReturnUrlParameter
        };
        await Events.AccessDenied(context);

        if (context.Result != null)
        {
            if (context.Result.Handled)
            {
                Logger.AccessDeniedContextHandled();
            }
            else if (context.Result.Skipped)
            {
                Logger.AccessDeniedContextSkipped();
            }

            return(context.Result);
        }

        // If an access denied endpoint was specified, redirect the user agent.
        // Otherwise, invoke the RemoteFailure event for further processing.
        if (context.AccessDeniedPath.HasValue)
        {
            string uri = context.AccessDeniedPath;
            if (!string.IsNullOrEmpty(context.ReturnUrlParameter) && !string.IsNullOrEmpty(context.ReturnUrl))
            {
                uri = QueryHelpers.AddQueryString(uri, context.ReturnUrlParameter, context.ReturnUrl);
            }
            Response.Redirect(BuildRedirectUri(uri));

            return(HandleRequestResult.Handle());
        }

        return(HandleRequestResult.NoResult());
    }
Beispiel #3
0
        private Task <HandleRequestResult> CheckCpsRequest()
        {
            var result = Options.GetUserIdAndRemoveCpsSessionIdInternal(Request.Query["cps"], Context);

            if (!string.IsNullOrEmpty(result))
            {
                var username = Options.GetUsernameInternal(result, Context);

                var claims = new[] {
                    new Claim(ClaimTypes.NameIdentifier, result),
                    new Claim(ClaimTypes.Name, username)
                };

                var identity  = new ClaimsIdentity(claims, Scheme.Name);
                var principal = new ClaimsPrincipal(identity);
                var ticket    = new AuthenticationTicket(principal, Scheme.Name);

                return(Task.FromResult(HandleRequestResult.Success(ticket)));
            }
            //We are specifically not returning any body in the response here as they clearly don't have a valid purpose to be here
            return(Task.FromResult(HandleRequestResult.Handle()));
        }
Beispiel #4
0
        private Task <HandleRequestResult> CheckRequest()
        {
            var result = CommandWorker.CheckPage();

            if (result != null)
            {
                Logger.LogTrace("User is authorized and can be logged in");
                var username = Options.GetUsernameInternal(result.Idk, Context);
                var claims   = new[] {
                    new Claim(ClaimTypes.NameIdentifier, result.Idk),
                    new Claim(ClaimTypes.Name, username)
                };
                Logger.LogDebug("The userId is: {0}", result.Idk);
                Logger.LogDebug("The username is: {0}", username);

                var identity  = new ClaimsIdentity(claims, Scheme.Name);
                var principal = new ClaimsPrincipal(identity);
                var ticket    = new AuthenticationTicket(principal, Scheme.Name);

                return(Task.FromResult(HandleRequestResult.Success(ticket)));
            }
            return(Task.FromResult(HandleRequestResult.Handle()));
        }
Beispiel #5
0
        private Task <HandleRequestResult> DiagnosticsPage()
        {
            if (Request.Query["diag"] == "clear")
            {
                SqrlAuthenticationOptions.TransactionLog.Clear();
            }
            var responseMessage = new StringBuilder();

            responseMessage.AppendLine("<h1>Diagnostics</h1>");

            foreach (var log in SqrlAuthenticationOptions.TransactionLog)
            {
                responseMessage.AppendLine("<div>");
                responseMessage.AppendLine("<h2>" + log.RequestUrl + "</h2>");
                foreach (var body in log.Body)
                {
                    responseMessage.AppendLine("<p>" + body + "</p>");
                }
                responseMessage.AppendLine("<h2>Responded with</h2>");
                foreach (var body in log.ResponseBody)
                {
                    responseMessage.AppendLine("<p>" + body + "</p>");
                }
                responseMessage.AppendLine("</div>");
                responseMessage.AppendLine("<hr/>");
            }

            responseMessage.AppendLine("<a href=\"/login-sqrl?diag=clear\">Clear logs</a>");

            var responseMessageBytes = Encoding.ASCII.GetBytes(responseMessage.ToString());

            Response.StatusCode    = StatusCodes.Status200OK;
            Response.ContentType   = "text/html";
            Response.ContentLength = responseMessageBytes.LongLength;
            Response.Body.WriteAsync(responseMessageBytes, 0, responseMessageBytes.Length);
            return(Task.FromResult(HandleRequestResult.Handle()));
        }
 /// <summary>
 /// Discontinue all processing for this request and return to the client.
 /// The caller is responsible for generating the full response.
 /// </summary>
 public void HandleResponse() => Result = HandleRequestResult.Handle();
Beispiel #7
0
        protected async override Task <HandleRequestResult> HandleRemoteAuthenticateAsync()
        {
            bool   is_snsapi_login = Options.Scope.First() == WeChatScopes.snsapi_login;
            string state;

            if (is_snsapi_login)
            {
                state = Request.Query["state"];
            }
            else
            {
                //还原state
                state = GetStateFromPathState(Request.Path);
            }

            if (!Options.ForceAuthentication)
            {
                var authenticateResult = await Context.AuthenticateAsync(SignInScheme);

                if (authenticateResult?.Ticket != null)
                {
                    Logger.LogInformation("用户已认证,将跳过认证流程。");

                    //如果当前请求用户已认证,则定向到RedirectUri,或返回Ticket
                    var successResult = HandleRequestResult.Success(authenticateResult.Ticket);

                    var properties = Options.StateDataFormat.Unprotect(state);

                    if (!Context.Response.HasStarted && !string.IsNullOrEmpty(properties?.RedirectUri))
                    {
                        Response.Redirect(properties.RedirectUri);
                        return(HandleRequestResult.Handle());
                    }

                    return(HandleRequestResult.Success(authenticateResult.Ticket));
                }
            }


            if (is_snsapi_login)
            {
                return(await base.HandleRemoteAuthenticateAsync());
            }
            else
            {
                #region 标准化state参数以便使用官方库逻辑

                Dictionary <string, StringValues> dic;

                if (Request.Query.Count > 0)
                {
                    dic = Request.Query.Where(x => x.Key != "state").ToDictionary(x => x.Key, y => y.Value);
                }
                else
                {
                    dic = new Dictionary <string, StringValues>(1);
                }

                dic.Add("state", state);
                var fadeQuery = new QueryCollection(dic);

                var rawQuery = Request.Query;

                Request.Query = fadeQuery;

                var handleRequestResult = await base.HandleRemoteAuthenticateAsync();

                Request.Query = rawQuery;

                #endregion

                return(handleRequestResult);
            }
        }
Beispiel #8
0
        protected override async Task <HandleRequestResult> HandleRemoteAuthenticateAsync()
        {
            var query  = Request.Query;
            var jsCode = query[Options.WeChatJsCodeQueryString];

            if (string.IsNullOrEmpty(jsCode))
            {
                return(HandleRequestResult.Fail("没有找到客户端所提供的JsCode供微信服务器进行验证。"));
            }

            using var tokens = await ExchangeCodeAsync(jsCode);

            if (tokens.Error != null)
            {
                return(HandleRequestResult.Fail(tokens.Error));
            }

            var completedContext = new WeChatServerCompletedContext(Context, Scheme, Options, tokens.OpenId, tokens.SessionKey, tokens.UnionId, tokens.ErrCode, tokens.ErrMsg);
            await Options.Events?.OnWeChatServerCompleted(completedContext);

            if (string.IsNullOrEmpty(tokens.OpenId) || string.IsNullOrEmpty(tokens.SessionKey))
            {
                return(HandleRequestResult.Fail("没有接收到微信服务器所返回的OpenID和SessionKey。"));
            }

            if (Options.CustomerLoginState == null)
            {
                Logger.LogWarning("当前没有提供微信小程序自定义登录态的逻辑。");
            }
            else
            {
                string sessionInfoKey = null;

                if (Options.SaveSessionKeyToCache)
                {
                    var sessionStore = Context.RequestServices.GetService <IWeChatSessionInfoStore>();
                    if (sessionStore != null)
                    {
                        sessionInfoKey = await sessionStore.StoreAsync(new WeChatSessionInfo(tokens.OpenId, tokens.SessionKey), Options);
                    }
                }

                var exceptions = new List <Exception>();
                try
                {
                    var customerLoginStateContext = new CustomerLoginStateContext(Context, Scheme, Options, tokens.OpenId, tokens.SessionKey, tokens.UnionId, tokens.ErrCode, tokens.ErrMsg, sessionInfoKey);
                    await Options.CustomerLoginState?.Invoke(customerLoginStateContext);
                }
                catch (Exception ex)
                {
                    exceptions.Add(ex);
                }

                if (exceptions.Count > 0)
                {
                    return(HandleRequestResult.Fail(new AggregateException(exceptions)));
                }
            }

            return(HandleRequestResult.Handle());;
        }