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); }
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 } }
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); }
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)); }
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); }
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); }
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 } }
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); }