Use google recaptcha with Angular and WebAPI - c#

I'm using Angular js front end application and web API backend. I want to use google recaptcha in the front end application. I can get widget displayed by referring following URL. https://developers.google.com/recaptcha/docs/display. This document doesn't talk about server-side validation with the secret key. But I have noticed some asp.net developers use server side implementation to validate google recaptcha response with the secret key. Do I need to do server-side validation with the secret key and what is the best way to do that in relating to angular and web API?

Yes, you need to do server side validation otherwise your unauthenticated API endpoints aren't protected by direct calls that don't go through your website.
The solution is pretty straight-foward and is detailed here:
https://developers.google.com/recaptcha/docs/verify
But a very simple example of a method that would validated the g-recaptcha-response given by the website would look like this:
public bool Validate(string encodedResponse)
{
if (string.IsNullOrEmpty(encodedResponse)) return false;
var secret = **your secret**;
if (string.IsNullOrEmpty(secret)) return false;
var client = new System.Net.WebClient();
var googleReply = client.DownloadString(
$"https://www.google.com/recaptcha/api/siteverify?secret={secret}&response={encodedResponse}");
return JsonConvert.DeserializeObject<RecaptchaResponse>(googleReply).Success;
}
RecaptchaResponse is a simple class we have that looks like this:
public class RecaptchaResponse
{
[JsonProperty("success")]
public bool Success { get; set; }
[JsonProperty("error-codes")]
public IEnumerable<string> ErrorCodes { get; set; }
[JsonProperty("challenge_ts")]
public DateTime ChallengeTs { get; set; }
[JsonProperty("hostname")]
public string Hostname { get; set; }
}

Related

How to utilise Entity Framework with a database hierarchy from API data

I might not have worded this question in the correct format as it's difficult to explain what the problem is. From the research I've gathered I think database hierarchy is something that I'm trying to utilize when using Entity Framework to create a database, I'll try to explain my problem in the best way possible.
Firstly, I'm running a Visual Studio 2019 project with a console application. This is my Program.cs file which is currently using a get request from an API URL with RESTSHARP then performing deserialization.
static void Main(string[] args)
{
getAPIData()
}
public static void getAPIData()
{
var client = new RestClient(URL);
var request = new RestRequest();
var response = client.Execute(request);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
string rawResponse = response.Content;
Requests.Rootobject result = JsonConvert.DeserializeObject<Requests.Rootobject>(rawResponse);
}
}
As you can see above, the raw data that's gathered from the URL (my API) is converted to a JSON format. And when I debug the code, it stores the code perfectly into the Requests DTO, as I'll show below.
public class Requests
{
public int Id { get; set; }
public class Rootobject
{
public Operation operation { get; set; }
}
public class Operation
{
public Result result { get; set; }
public Detail[] details { get; set; }
}
public class Result
{
public string message { get; set; }
public string status { get; set; }
}
public class Detail
{
public string requester { get; set; }
public string workorderid { get; set; }
public string accountname { get; set; }
}
}
The recently converted API data is now stored in this class in this correct format. Which is what's necessary for the API itself since it comes in numerous classes. This object now holds all the relevant data I need, now I can utilize the entity framework to generate an appropriate table that will hold this into an SQL server.
Here is the Entity Framework class.
public class TransitionContext : DbContext
{
private const string connectionString = #"(connection string here)";
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(connectionString);
}
public DbSet<Requests> Requesting { get; set; }
}
Currently, when I run the package manager console commands to build a migration and setup a connection to the server, it works fine (Obviously I've not included my real connection string for privacy reasons). However, when I use the "Update-Database" command from the DbSet which is my DTO for the API data. The only key that is displayed is an ID, nothing else.
SQL requests table
All that's generated here is an Id key from the Requests Dto. Now, on the API itself, there is no ID key, I added it in there because Entity Framework said I had to have an ID key and was displaying errors until I made one. But now that's all it's generating when I "Update-Database".
The reason why I showed as much data as I have done, is because the process is simply exporting the converted JSON data (a recently gathered API) into an SQL table. Or tables so that it supports a hierarchy, anything that will map correctly from the DTO to the database. But as of right now, my only issue with the project is that only an ID is being generated.
So I'm not sure where I'm going wrong here or how to get this working as I intend it to work. Apologies for the really long explanation, I tried to condense it as much as I could, any help would be appreciated and any questions I'm free to answer, thank you!

Saving the information in database and then Post request to external API using .NET CORE

I am new to .NET CORE and I'm trying to work with external API's using .NET CORE application MVC architecture. As a newbie it is really difficult for me to grasp the root cause of MVC, well having said that I did my own research and have understand a lot of things. Right now I have two Questions (1st one is about suggesting How to start, 2nd one is about the work I have done till now)
Question 1 (Suggestion)
So as I said I'm trying to work on calling external API's using MVC architecture. What I want to do is lets suppose the admin is logging in first time, the first username and password is default "admin" and "myadminpassword" respectively. To login admin have to provide with a new password which is send as a request body to the API. Now I want that new password to save to my db and then from there to the API endpoint. Is it doable? and Is it a good idea?
Question 2 (Approach Till Now)
So getting help from a lots of tutorial below is my code what I have done till now.
Main_Application / Areas / Application / View / Home / Index.cshtml
#using (Html.BeginForm("Login", "WhAuth", FormMethod.Post))
{
<label>
Username:
<input type="text" placeholder="admin" readonly />
</label>
<br />
<label>
Password:
<input type="text" placeholder="*****" readonly />
</label>
<br />
<label>
Enter New Password:
#Html.TextAreaFor(m => m.New_password, 5,5,new { })
</label>
<br />
<button class="btn btn-default" type="submit">Sign up as Admin</button>
}
Main_Application / Areas / Application / Models / AdminLoginModel.cs
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
namespace PTCConnector.Areas.Whatsapp.Models
{
public class AdminLoginModel
{
public string Df_username = "admin";
public string Df_password = "anySecretPassword";
[Required(ErrorMessage = "New Password Is Required")]
public string New_password { get; set; }
}
}
Main_Application / Models / DB / whapp.cs
public class whapp : BaseEntity
{
public string Username { get; set; }
public string Password { get; set; }
public string New_Password { get; set; }
public string Token { get; set; }
public string WhatsappId { get; set; } //Whatsapp ID
public string type { get; set; }
public string recipient_type { get; set; }
public string Messagebody { get; set; }
public string URL { get; set; }
public string Group_id { get; set; }
public string Caption { get; set; }
public string Media_Id { get; set; }
public string Status { get; set; }
public string GroupName { get; set; }
}
Main_Application / Data / ApplicationDBContext.cs
public DbSet<whapp> whapp { get; set; }
Main_Application / Areas / Application / Controllers / WhAuthController.cs
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using PTCConnector.Areas.Whatsapp.Models;
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
namespace PTCConnector.Areas.Whatsapp.Controllers
{
[Area("Whatsapp")]
[TypeFilter(typeof(AdminActionFilter))]
[Authorize(Roles = "Admin")]
public class WhAuthController : Controller
{
public AdminLoginModel whLogin = new AdminLoginModel();
public async Task Login()
{
HttpClientHandler clientHandler = new HttpClientHandler
{
ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => { return true; }
};
var client = new HttpClient(clientHandler);
byte[] bytes = Encoding.UTF8.GetBytes($"{whLogin.Df_username}:{whLogin.Df_password}");
var Base64Credentials = Convert.ToBase64String(bytes);
System.Diagnostics.Debug.WriteLine(Base64Credentials);
// Set Base64Credentials as Authorization header with Prefix
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Base64Credentials);
// Just some data for POST, change freely!
var data = new Dictionary<string, string>
{
{ "new_password", $"{whLogin.New_password}" } //
};
System.Diagnostics.Debug.WriteLine(data.Values);
Console.WriteLine("here 1");
// Encode the data in FORM URL Data
var content = new FormUrlEncodedContent(data);
// Make Async Post Call with Client. Parameters are URL and Data to POST!
var response = await client.PostAsync("https://localhost:9090/v1/users/login", content);
// Async!! - Read the response content as String
var responseString = await response.Content.ReadAsStringAsync();
// Print out the Response String for Debugging!
//Console.WriteLine(responseString);
System.Diagnostics.Debug.WriteLine(responseString);
System.Diagnostics.Debug.WriteLine("Check");
Console.WriteLine("CheckNow");
}
}
}
Main_Application / Startup.cs
services.AddDbContext<ApplicationDbContext> ... //
services.AddHttpClient("WhappClient", client =>
{
client.BaseAddress = new Uri("https://localhost:9090/v1/users/login");
client.DefaultRequestHeaders.Add("username", "admin");
client.DefaultRequestHeaders.Add("password", "anySecretPassword");
});
Everything is working fine, my main aim is to post the data into the database also, so the information could be saved, also the return result from the API's also have to be saved in a database for future use.
Edit
The application is running on docker container the path of which is https://localhost:9090/
My aim is that when the user fill the information of new_password in the input field and press submit, the application should hit the controller with the new_password like below.
var data = new Dictionary<string, string>
{
{ "new_password", $"{whLogin.New_password}" } //
};
which is then hit to the specific endpoint as mentioned
await client.PostAsync("https://localhost:9090/v1/users/login", content);
the return will be a token that I want to save in the database for future endpoint calls, moreover then the given new_password also be saved in the hash format in my database.
Starting an answer since I can't simply comment yet. Can you provide some more information and context as to what you are trying to accomplish here? What is the external API's purpose, as it appears to be another local project? Is the project we are looking at an MVC project or a Web API project? Is the user store local or are you using an external identity provider?
So far you've taken in some input data, encoded it as a Base64 string and then sent it to your other local API. Where does the database save, that you mentioned, happen? Also, if your storing the password in a database, make sure you take the proper steps to hash and salt it before saving it. Honestly you should just use the built in ASP.NET Identity if you need a user/authentication framework. As someone else commented, where are you getting hung up, what is going wrong?
I hope this doesn't sound interrogating with all the questions lol! I'm just sure we could help some more if we get some more background and details about whats going on. If you can provide some of this info, I can edit my answer to hopefully be of more assistance.

How do document service responses in ServiceStack with Servicestack swagger-api (1.2)

I am using swagger ui for the documentation of my ServiceStack web-services which works quite nice. However I did not find a way to add any information about the responses of those web-services (json). So when the GET method of my service looks like this:
public object Get(CustomerData customers)
{
List<CustomerDAO> customers = DataProvider.GetAllCustomers();
return customers;
}
public class CustomerDAO
{
// this is important information which needs to be visible in swagger-ui
public string Name { get; set; }
public string SomeImportantProperty { get; set; }
public string AnotherPropery { get; set; }
public string AlsoWorthDocumenting { get; set; }
// and so on...
}
I need a short description of each property in the documentation (swagger-ui) which is essential for using those web-services.
I am using ServiceStack 3.9.74 but this should also apply to the latest ServiceStack version. If not please let me know.
I was wondering how I can get this information in swagger, or if not, how to supply such important information to the developers who have to work with my web services. I am also open for any other approaches or best practices which will work in the environment of ServiceStack.
I'm not sure about your version of ServiceStack. In the latest version you would have your request dto inheirt IReturn<ReturnClassHere> which would tell swagger to look at that return class.
So your CustomerData class would look something like this:
public class CustomerData : IReturn<List<CustomerDAO>>
{
}
Although it would probably be better to setup another dto for your response that would be returned instead. Maybe something like CustomerDataResponse.

Encrypting messages over ServiceStack

Given an app that needs to exchange info such as ConsumerKey/ConsumerSecret for oAuth from
- server running "WebApi" over ServiceStack
- consumer is a desktop app
Looking to encrypt the messages using Public/Private keys which are already in place
Is there any support for encrypting/decrypting messages, hopefully transparently ? i.e. the encrypting/decryption is handled via say Filters on the server ?
OR
any workaround on how to do this ?
FYI - the server already requires SSL and requests are authenticated, however the registration is free/automated, hence the need for encryption
Update
The Encrypted Messaging Feature released in v4.0.42 now enables a secure channel for all Services offering protection to clients who can now easily send and receive encrypted messages over unsecured HTTP.
There's no published support for Message Level encryption built into the ServiceStack at the moment, although this is something we're thinking of adding in the future. Below is an example of an approach you could try with ServiceStack today for exploratory purposes (it will require more R&D on your part to come up with a good solid design), and as this is an area that may change in future, it's not a use-case we're supporting right now, but here's something that could work with ServiceStack as it is now:
class EncryptedRequest
{
//Name of the request type
public string Type { get; set; }
//Serialized Request DTO using something like JSON
public string EncryptedBody { get; set; }
//optional: let server the private key that was used (if multiple)
public string PrivateKeyMd5Hash { get; set; }
}
class EncryptedResponse
{
//Name of the response type
public string Type { get; set; }
//Serialized Response DTO
public string EncryptedBody { get; set; }
//optional
public string PublicKeyMd5Hash { get; set; }
}
Here is a convenient CryptUtils wrapper that makes it easy to create Public/Private keys as well as being able to Encrypt/Decrypt text using them.
Then you can have a single service, and do something like:
class EncryptedService : Service
{
const string PublicKey = ...;
const string PrivateKey = ...;
EncryptedResponse Any(EncryptedRequest request)
{
var requestType = Type.GetType("{0}.{1}"
.Fmt(typeof(EncryptedRequest).Namespace, request.Type));
var json = CryptUtils.Decrypt(PrivateKey, request.EncryptedBody);
var requestDto = JsonSerializer.DeserializeFromString(json,requestType);
var responseDto = GetAppHost().Config.ServiceController
.Execute(requestDto, base.RequestContext);
return new EncryptedResponse {
Type = responseDto.GetType().Name,
EncryptedBody = CryptUtils.Encrypt(PublicKey, responseDto.ToJson()),
};
}
}
The client would also need a copy of the Public/Private key pair which you would exchange out-of-band.

Not working maxlengthurl(too longer) in any browser

I am looking for new wcf rest web service in asp.net 4.0 using vs2010.
here is my code for passing url:
"homewizard/Service1.svc/monthlytips/country_state=US_IL_N/tip_code=NoInformation/feature=ACC,FAHD,WHG,FP,WA,DY,DWSH,GD,REF,STV,OVN,MW,CPTR,ATT,ROOF,RG,BSMT,FDN,SPX,GAR,EGF,PLB,DOOR,WIND,WS,LWN,DKG,PF,BBQ,WSD,OWF,DWY,OLIT,HL,SPTC,CF,WF,CPTS,DVB,FURW,FURL,FURU,MAT,BATH,KITC,CLST,LITE,SD,COD,FE,EMS,PC,SS,MED,EAUD,ENR,GARR,INR,MGR,TAXR,TELR,CGD,DOOR,WIND,WS/dwelling_type=1/tip_priority=1/month=3/tip_knowledge_level=1/tipbr_ensav=0/tipbr_safe=0/tipbr_avoid=1/tipbr_comfort=1/tipbr_value=1/tipbr_appear=1/tipbr_green=0/tipbr_money=0/tipbr_space=1/tipbr_allergy=2/tipbr_elderly=2/tipbr_children=2/tip_location_temp=0/tip_location_humidity=0"
output:Bad Request - Invalid URL HTTP Error 400. The request URL is invalid.
my web config is: httpRuntime maxUrlLength="1024"
but it's working my local host not in server pc.
thanks in advance.
To be honest your issue is that that's not a restfull URL, the url should just be the location of the resource you are dealing with, the body of the request should contain the details of the request (as xml or json for example). It will both solve your problem and result in less code to manage the parameters via deserialization into a request object server side, not to mention clear up that url.
UPDATE
Are you sure thats a GET and not a PUT, what is the call meant to do?
If it is a GET I'd do something like the following...
Service Interface
[WebGet(UriTemplate = "monthlytips")]
AppropriateReturnType MonthlyTips(MonthlyTip monthlytip);
DTO Object
public class MonthlyTip
{
public string CountryState { get; set; }
public string TipCode { get; set; }
public List<string> Feature { get; set; }
public int DwellingType { get; set; }
public int TipPriority { get; set; }
...
...
}
Thats off the top of my head so it might need a little refining and you'll need to implement the interface, finish the DTO and so on but that's the approach you should take.

Categories

Resources