Example #1
0
        public static void BitIdLogin(string address, string signature, string uri)
        {
            BitIdCredentials credentials = new BitIdCredentials
            {
                address   = address,
                signature = signature,
                uri       = uri
            };

            ProcessRespondBitId(credentials, HttpContext.Current.Response);
        }
Example #2
0
        protected void ProcessRespondBitId(BitIdCredentials credentials, HttpResponse response)
        {
            BitcoinAddress testAddress = new BitcoinAddress(credentials.address);

            if (testAddress.VerifyMessage(credentials.uri, credentials.signature))
            {
                // woooooo

                try
                {
                    if (CurrentUser != null)
                    {
                        if ((string)GuidCache.Get(credentials.uri + "-Intent") == "Register")
                        {
                            // the currently logged-on user desires to register this address
                            // so set currentUser bitid
                            CurrentUser.BitIdAddress = credentials.address;
                            // Then go do something else, I guess? Flag somehow to original page
                            // that the op is completed?
                            GuidCache.Set(credentials.uri + "-Intent", "Complete");
                        }
                    }

                    if (GuidCache.Get(credentials.uri + "-Logon") as string == "Unauth")
                    {
                        Person person = Person.FromBitIdAddress(credentials.address);

                        // TODO: If above throws, show friendly "unknown wallet" message

                        // TODO: Determine last logged-on organization. Right now, log on to Sandbox.

                        GuidCache.Set(credentials.uri + "-LoggedOn",
                                      person.Identity.ToString(CultureInfo.InvariantCulture) + ",1,,BitId 2FA");
                    }
                }
                catch (Exception e)
                {
                    Persistence.Key["BitIdLogin_Debug_Exception"] = e.ToString();
                }

                // TODO: Error codes

                response.StatusCode = 200;
                response.SetJson();
                response.Write("{\"address\":\"" + credentials.address + "\",\"signature\":\"" + credentials.signature +
                               "\"}");
                response.End();
            }
            else
            {
                response.StatusCode = 401; // Be a bit more friendly in your return codes
            }
        }
Example #3
0
        public void Login_BitidRequestMessageIsValid_ReturnsJsonToken()
        {
            // Arrange
            var mockJwtIssuer = A.Fake <IOptions <JwtIssuerOptions> >();
            var mockLogger    = A.Fake <ILogger <IdentityController> >();

            var credentials = new BitIdCredentials();

            var controller = new IdentityController(mockJwtIssuer, mockLogger);

            // Act
            var actionResult = controller.Post(credentials);

            // Assert
            Assert.Equal(true, true);
        }
Example #4
0
        public async Task <IActionResult> Post([FromForm] BitIdCredentials request)
        {
            string jsonResponseToken = string.Empty;

            BitIdResponse response = request.VerifyMessage();

            jsonResponseToken = JsonConvert.SerializeObject(response, _serializerSettings);
            if (response.Success)
            {
                // use attribute >> [Authorize(Policy = Constants.AuthorizationPolicy)]
                var identity = GetClaimsIdentity(request.Address);

                var claims = new[]
                {
                    new Claim(JwtRegisteredClaimNames.Sub, request.Address),
                    new Claim(JwtRegisteredClaimNames.Jti, await _jwtOptions.JtiGenerator()),
                    new Claim(JwtRegisteredClaimNames.Iat, ToUnixEpochDate(_jwtOptions.IssuedAt).ToString(), ClaimValueTypes.Integer64),
                    identity.FindFirst(Constants.ClaimType)
                };
                // Create the JWT security token and encode it.
                var jwt = new JwtSecurityToken(
                    issuer: _jwtOptions.Issuer,
                    audience: _jwtOptions.Audience,
                    claims: claims,
                    notBefore: _jwtOptions.NotBefore,
                    expires: _jwtOptions.Expiration,
                    signingCredentials: _jwtOptions.SigningCredentials);
                var encodedJwt = new JwtSecurityTokenHandler().WriteToken(jwt);

                // Serialize and return the response
                var responseToken = new
                {
                    access_token = encodedJwt,
                    expires_in   = (int)_jwtOptions.ValidFor.TotalSeconds
                };

                jsonResponseToken = JsonConvert.SerializeObject(responseToken, _serializerSettings);
            }

            return(new ObjectResult(jsonResponseToken));
        }
Example #5
0
        public void Login_BitidRequestMessageIsValid_ReturnsTrue()
        {
            // Arrange
            Key            privateKey = new Key(); //Create private key
            BitcoinSecret  secret     = privateKey.GetBitcoinSecret(Network.Main);
            BitcoinAddress pubAddress = secret.GetAddress();
            Guid           guid       = Guid.NewGuid();
            string         guidString = guid.ToString().Replace("-", "");

            long   ticks     = DateTime.UtcNow.Ticks;
            string nonce     = guidString + ticks.ToString("x");
            string bitIdUri  = "bitid://localhost/api/identity?x=" + nonce + "&u=1";
            string signature = privateKey.SignMessage(bitIdUri);

            var request = new BitIdCredentials(pubAddress.ToString(), bitIdUri, signature);

            // Act
            BitIdResponse response = request.VerifyMessage();

            // Assert
            Assert.True(response.Success);
        }
Example #6
0
        protected void Page_Load(object sender, EventArgs e)
        {
            // Check if this is the first run ever. If so, redirect to Init.

            if (!SupportFunctions.DatabaseConfigured)
            {
                // ReSharper disable once Html.PathError   <-- this line is required for Resharper to not flag the next line as invalid
                Response.Redirect("/Initialize", true);
                return;
            }

            // Persistence.Key["Debug_RawData"] = Request.ToRaw();

            // Check for POST data - for BitId via Webform

            if (Request.HttpMethod == "POST")
            {
                // We should ONLY get here if we're getting a BitId by Webform submission.

                // Persistence.Key["BitId_RawData"] = Request.ToRaw();

                if (Request.Params["address"] != null)
                {
                    // yes, indeed looks like it

                    BitIdCredentials credentials = new BitIdCredentials
                    {
                        address   = Request.Params["address"],
                        uri       = Request.Params["uri"],
                        signature = Request.Params["signature"]
                    };

                    ProcessRespondBitId(credentials, Response);
                    return;
                }
                if (Request.ContentType == "application/json")
                {
                    BitIdCredentials credentials =
                        new JavaScriptSerializer().Deserialize <BitIdCredentials> (
                            new StreamReader(Request.InputStream).ReadToEnd());
                    // TODO: untested but seems to work. Throws?

                    ProcessRespondBitId(credentials, Response);
                    return;
                }
            }

            string requestHost = Request.Url.Host;

            // If this is the Dev Sandbox, autologin

            if ((requestHost == "sandbox.swarmops.com" || requestHost == "dev.swarmops.com") &&
                PilotInstallationIds.IsPilot(PilotInstallationIds.DevelopmentSandbox) &&
                Request.QueryString["SuppressAutologin"] != "true")
            {
                DashboardMessage.Set("<p>You have been logged on as <strong>Sandbox Administrator</strong> to the Swarmops Development Sandbox.</p><br/><p>This machine runs the latest development build, so you may run into diagnostic code and half-finished features. All data here is bogus test data and is reset every night.</p><br/><p><strong>In other words, welcome, and play away!</strong></p>");
                FormsAuthentication.SetAuthCookie(Authority.FromLogin(Person.FromIdentity(1), Organization.Sandbox).ToEncryptedXml(), true);
                Response.Redirect(HttpContext.Current.Request ["ReturnUrl"]);   // Returns to the requested URL with auth cookie set
            }

            // If we're on an Open Ledgers domain, autologin as Open Ledgers

            Organization organizationOpenLedgers = Organization.FromOpenLedgersDomain(requestHost); // returns null if doesn't exist

            if (organizationOpenLedgers != null)
            {
                DashboardMessage.Set(String.Format(Resources.Pages.Security.Login_AsOpenLedgers, organizationOpenLedgers.Name));
                FormsAuthentication.SetAuthCookie(Authority.FromLogin(Person.FromIdentity(Person.OpenLedgersIdentity), organizationOpenLedgers).ToEncryptedXml(), true);
                if (HttpContext.Current.Request["ReturnUrl"] == "/")
                {
                    Response.Redirect(@"/Ledgers/Balance");
                }
                else
                {
                    Response.Redirect(HttpContext.Current.Request["ReturnUrl"]);  // Returns to the requested URL with auth cookie set
                }
            }

            // Check for SSL and force it

            // Special case for CloudFlare deployments - there is a case where somebody will get their connections de-SSLed at the server

            string cloudFlareVisitorScheme = Request.Headers["CF-Visitor"];
            bool   cloudFlareSsl           = false;

            if (!string.IsNullOrEmpty(cloudFlareVisitorScheme))
            {
                if (cloudFlareVisitorScheme.Contains("\"scheme\":\"https\""))
                {
                    cloudFlareSsl = true;
                }
            }

            // TODO: Same thing for Pound/HAProxy deployments

            // Rewrite if applicable

            if (Request.Url.ToString().StartsWith("http://") && !cloudFlareSsl)
            // only check client-side as many server sites de-SSL the connection before reaching the web server
            {
                if (!Request.Url.ToString().StartsWith("http://dev.swarmops.com/") &&
                    !(Request.Url.ToString().StartsWith("http://*****:*****@"//" + vanityOrganization.VanityDomain + @"/Signup";
                // this.LabelSelfSignup.Text = String.Format (Resources.Pages.Security.Login_SelfSignup, vanityOrganization.Name);
                // this.LabelSelfSignupHeader.Text = Resources.Pages.Security.Login_SelfSignupHeader;
                // this.PanelJoin.Visible = true;
            }


            // If we're debugging, enable the auto- / impersonation login. This MUST NEVER fire outside of development environment.

            if (Debugger.IsAttached && Path.DirectorySeparatorChar == '\\')
            // on Windows, with a debugger attached, so this is not a production environment
            {
                // but check that we're running against Localhost as well

                if (Request.Url.ToString().StartsWith("http://localhost:"))
                {
                    this.PanelCheat.Visible = true;
                }
            }


            // this.ImageCultureIndicator.Style[HtmlTextWriterStyle.MarginTop] = "-3px";
            // this.ImageCultureIndicator.Style[HtmlTextWriterStyle.MarginRight] = "3px";
            // this.ImageCultureIndicator.Style[HtmlTextWriterStyle.Cursor] = "pointer";

            _cacheVersionMark = Logic.Support.Formatting.SwarmopsVersion;
            if (_cacheVersionMark.StartsWith("Debug"))
            {
                _cacheVersionMark = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.ffff");
            }
            _cacheVersionMark = SHA1.Hash(_cacheVersionMark).Replace(" ", "").Substring(0, 8);

            Localize();

            // Generate BitID tokens

            Guid   guid       = Guid.NewGuid();
            string guidString = guid.ToString().Replace("-", "");

            string nonce = guidString + DateTime.UtcNow.Ticks.ToString("x8");

            string hostName = Request.Url.Host;

            string bitIdUri = "bitid://" + hostName + "/Security/Login.aspx/BitIdLogin?x=" + nonce;

            /*   -- commented out: NEVER permit BitId over non-SSL
             * if (Request.Url.ToString().StartsWith ("http://") && !cloudFlareSsl)
             * {
             *  bitIdUri += "&u=1";
             * }*/

            this.LiteralUri.Text   = HttpUtility.UrlEncode(bitIdUri);
            this.LiteralNonce.Text = nonce;

            GuidCache.Set(bitIdUri + "-Logon", "Unauth");

            // TODO: need to NOT USE GOOGLE CHARTS for this but bring home a free QR package

            this.ImageBitIdQr.ImageUrl =
                "https://chart.googleapis.com/chart?cht=qr&chs=400x400&chl=" + HttpUtility.UrlEncode(bitIdUri);
        }
Example #7
0
        protected string _cacheVersionMark; // CSS cache buster

        protected static void ProcessRespondBitId(BitIdCredentials credentials, HttpResponse response)
        {
            BitcoinPubKeyAddress testAddress = new BitcoinPubKeyAddress(credentials.address);

            if (testAddress.VerifyMessage(credentials.uri, credentials.signature))
            {
                // woooooo

                try
                {
                    // Test for registration

                    string intent = GuidCache.Get(credentials.uri + "-Intent") as string;

                    if (!string.IsNullOrEmpty(intent))
                    {
                        if (intent.StartsWith("Register"))
                        {
                            int    personId = Int32.Parse(intent.Substring("Register-".Length));
                            Person person   = Person.FromIdentity(personId);
                            person.BitIdAddress = credentials.address;
                            GuidCache.Set(credentials.uri + "-Intent", "Complete");
                        }
                    }

                    // Otherwise, test for logon

                    if (GuidCache.Get(credentials.uri + "-Logon") as string == "Unauth")
                    {
                        Person person = Person.FromBitIdAddress(credentials.address);

                        // TODO: If above throws, show friendly "unknown wallet" message

                        int lastOrgId = person.LastLogonOrganizationId;

                        if (lastOrgId == 0)
                        {
                            lastOrgId = Organization.SandboxIdentity;
                            person.LastLogonOrganizationId = lastOrgId;
                        }

                        GuidCache.Set(credentials.uri + "-LoggedOn",
                                      Authority.FromLogin(person, Organization.FromIdentity(person.LastLogonOrganizationId)).ToEncryptedXml());
                    }
                }
                catch (Exception e)
                {
                    Persistence.Key["BitIdLogin_Debug_Exception"] = e.ToString();
                }

                // TODO: Error codes

                response.StatusCode = 200;
                response.SetJson();
                response.Write("{\"address\":\"" + credentials.address + "\",\"signature\":\"" + credentials.signature +
                               "\"}");
                response.End();
            }
            else
            {
                response.StatusCode = 401; // Be a bit more friendly in your return codes
            }
        }
Example #8
0
        protected void Page_Load(object sender, EventArgs e)
        {
            // Check if this is the first run ever. If so, redirect to Init.

            if (!SwarmDb.Configuration.IsConfigured())
            {
                Response.Redirect("/Pages/v5/Init/", true);
                return;
            }

            // Persistence.Key["Debug_RawData"] = Request.ToRaw();

            // Check for POST data - for BitId via Webform

            if (Request.HttpMethod == "POST")
            {
                // We should ONLY get here if we're getting a BitId by Webform submission.

                Persistence.Key["BitId_RawData"] = Request.ToRaw();

                if (Request.Params["address"] != null)
                {
                    // yes, indeed looks like it

                    BitIdCredentials credentials = new BitIdCredentials
                    {
                        address   = Request.Params["address"],
                        uri       = Request.Params["uri"],
                        signature = Request.Params["signature"]
                    };

                    ProcessRespondBitId(credentials, Response);
                    return;
                }
                if (Request.ContentType == "application/json")
                {
                    BitIdCredentials credentials =
                        new JavaScriptSerializer().Deserialize <BitIdCredentials> (
                            new StreamReader(Request.InputStream).ReadToEnd());
                    // TODO: untested but seems to work. Throws?

                    ProcessRespondBitId(credentials, Response);
                    return;
                }
            }


            // If this is the Dev Sandbox, autologin

            if (Request.Url.Host == "dev.swarmops.com" &&
                PilotInstallationIds.IsPilot(PilotInstallationIds.DevelopmentSandbox) &&
                Request.QueryString["SuppressAutologin"] != "true")
            {
                Response.AppendCookie(new HttpCookie("DashboardMessage",
                                                     HttpUtility.UrlEncode(
                                                         "<p>You have been logged on as <strong>Sandbox Administrator</strong> to the Swarmops Development Sandbox.</p><br/><p>This machine runs the latest development build, so you may run into diagnostic code and half-finished features. All data here is bogus test data and is reset every night.</p><br/><p><strong>In other words, welcome, and play away!</strong></p>")));
                FormsAuthentication.SetAuthCookie("1,1", true);
                Response.Redirect("/");
            }

            // Check for SSL and force it

            // Special case for CloudFlare deployments - there is a case where somebody will get their connections de-SSLed at the server

            string cloudFlareVisitorScheme = Request.Headers["CF-Visitor"];
            bool   cloudFlareSsl           = false;

            if (!string.IsNullOrEmpty(cloudFlareVisitorScheme))
            {
                if (cloudFlareVisitorScheme.Contains("\"scheme\":\"https\""))
                {
                    cloudFlareSsl = true;
                }
            }

            // TODO: Same thing for Pound deployments

            // Rewrite if applicable

            if (Request.Url.ToString().StartsWith("http://") && !cloudFlareSsl)
            // only check client-side as many server sites de-SSL the connection before reaching the web server
            {
                if (!Request.Url.ToString().StartsWith("http://dev.swarmops.com/") &&
                    !Request.Url.ToString().StartsWith("http://localhost:"))
                {
                    Response.Redirect(Request.Url.ToString().Replace("http:", "https:"));
                }
            }

            this.ImageCultureIndicator.Style[HtmlTextWriterStyle.MarginTop]   = "-3px";
            this.ImageCultureIndicator.Style[HtmlTextWriterStyle.MarginRight] = "3px";
            this.ImageCultureIndicator.Style[HtmlTextWriterStyle.Cursor]      = "pointer";

            Localize();

            // Generate BitID tokens

            Guid   guid       = Guid.NewGuid();
            string guidString = guid.ToString().Replace("-", "");

            string nonce = guidString + DateTime.UtcNow.Ticks.ToString("x8");

            string hostName = Request.Url.Host;

            string bitIdUri = "bitid://" + hostName + "/Security/Login.aspx?x=" + nonce;

            if (Request.Url.ToString().StartsWith("http://") && !cloudFlareSsl)
            {
                bitIdUri += "&u=1";
            }

            this.LiteralUri.Text   = HttpUtility.UrlEncode(bitIdUri);
            this.LiteralNonce.Text = nonce;

            GuidCache.Set(bitIdUri + "-Logon", "Unauth");

            // TODO: need to NOT USE GOOGLE CHARTS for this but bring home a free QR package

            this.ImageBitIdQr.ImageUrl =
                "https://chart.googleapis.com/chart?cht=qr&chs=400x400&chl=" + HttpUtility.UrlEncode(bitIdUri);
        }