I am trying to develop Google site verification system using ASP.Net. Also using the Google explorer (https://developers.google.com/site-verification/v1/webResource/insert) to test the request method such as JSON and HTTP request format.
This is what I am sending to the Google.
POST https://www.googleapis.com/siteVerification/v1/webResource?verificationMethod=site&key={YOUR_API_KEY}
Content-Type: application/json
Authorization: Bearer xxxxxxxxxxxxxxx
X-JavaScript-User-Agent: Google APIs Explorer
{
"id": "myid",
"owners": [
"development#gmail.com"
],
"site": {
"type": "site",
"identifier": "http://www.example.net/"
}
}
I am getting following response from the Google.
{
"error": {
"errors": [
{
"domain": "global",
"reason": "backendError",
"message": "Backend Error"
}
],
"code": 503,
"message": "Backend Error"
}
}
>
IAuthorizationState authorization;
protected void Page_Load(object sender, EventArgs e)
{
if (googleClient != null)
{
if (IsPostBack)
{
authorization = googleClient.ProcessUserAuthorization();
if (authorization != null)
{
this.AccessToken = authorization.AccessToken;
}
else if (this.AccessToken == null)
{
googleClient.RequestUserAuthorization(scope: new[] { GoogleClient.Scopes.WebMaster.SiteVerification });
}
}
}
}
protected void Button1_Click(object sender, EventArgs e)
{
if (authorization != null)
{
IOWebMasterInsertGraph webMasterInsertGraph = googleClient.RequestForVerification(authorization);
}
}
public IOWebMasterInsertGraph RequestForVerification(IAuthorizationState authState)
{
if ((authState != null) && (authState.AccessToken != null))
{
WebRequest request = WebRequest.Create("https://www.googleapis.com/siteVerification/v1/webResource?verificationMethod=site");
string path = HostingEnvironment.MapPath(#"~/App_Data/GoogleInsert.json");
MemoryStream ms = new MemoryStream();
FileStream fileStreem = new FileStream(path, FileMode.Open, FileAccess.Read);
byte[] bytes = new byte[fileStreem.Length];
fileStreem.Read(bytes, 0, (int)fileStreem.Length);
ms.Write(bytes, 0, (int)fileStreem.Length);
request.ContentType = "application/json";
request.Method = "POST";
request.ContentLength = ms.Length;
ms.Seek(0, SeekOrigin.Begin);
using (Stream requestStream = request.GetRequestStream())
{
ms.CopyTo(requestStream);
}
WebResponse response = request.GetResponse();
if (response != null)
{
Stream responseStream = response.GetResponseStream();
if (responseStream != null)
{
//return GoogleGraph.Deserialize(responseStream);
return WebMasterInsertGraph.Deserialize(responseStream);
}
}
}
return null;
}
Does anyone know the reason for this?
Why don't you use the Google .NET client library for Site verification?
You even have a sample code for that.
Try it out...
I have found the answer myself.
The following has to be sent to the GoogleApi without the id in JSON. The verificationMethos has to be one you selected when getting token.
POST /siteVerification/v1/webResource?verificationMethod=file HTTP/1.1 Host: www.googleapis.com
Content-length: 138
Content-type: application/json
Authorization: Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
{
"owners": [
"sample#gmail.com" ],
"site": {
"identifier": "http://test.sample.com/",
"type": "SITE" }
}
Related
THE JSON STRING IS:
{ "errcode" : "0",
"errmsg" : SUCCESS",
"responseObject" :{ "result" :[{ "sjmj" : "ABCD",
"zzmmzw" : NULL,
}], "total" : 39 }}
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url);
request.Headers.Set("userKey", "vsc30r8f");
request.Proxy = null;
request.KeepAlive = false;
request.Method = "GET";
request.ContentType = "application/json; charset=UTF-8";
request.Accept = "application/json";
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream myResponseStream = response.GetResponseStream();
StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.UTF8);
string retString = myStreamReader.ReadToEnd();
myStreamReader.Close();
myResponseStream.Close();
if (response != null)
{
response.Close();
}
if (request != null)
{
request.Abort();
}
when i using Newtonsoft method in c# the code below
JObject jObj111 = JsonConvert.DeserializeObject(retString );
the application exception says"Newtonsoft.Json.JsonReaderException: Error parsing NaN value".
or i use
JObject jObj111 = JObject.Parse(retString )
the also application exception says"Newtonsoft.Json.JsonReaderException: Error parsing NaN value".
how can i solve the prblem thanks very much**
the retString is : { "errcode" : "0", "errmsg" : SUCCESS", "responseObject" :{ "result" :[{ "sjmj" : "ABCD", "zzmmzw" : NULL}], "total" : 39 }}
Calling microsoft graph API https://graph.microsoft.com/v1.0/subscribedSkus fails with
"code": "Authorization_RequestDenied",
"message": "Insufficient privileges to complete the operation.",
This is happening if we create a new user in the tenant who is non admin. But while calling this with Admin user it works just fine. Even it works for any microsoft user in the tenant.
This is the below code I used to try.
public static async Task TestAadGraph()
{
// using obo token of the user.
var graphToken = await GetTokenAsync(UserId, Token, "https://graph.microsoft.com");
var aadGraphClient = new AadGraphClient(new HttpClient());
var licenseResponse = await aadGraphClient.GetTenantLicenseDetailAsync(graphToken);
foreach (var license in licenseResponse)
{
Console.WriteLine("Sku ID: {0}", license.SkuId);
Console.WriteLine("Sku Part Number: {0}", license.SkuPartNumber);
foreach (var plan in license.ServicePlans)
{
Console.WriteLine("Plan Id: {0}", plan.ServicePlanId);
Console.WriteLine("Plan Name: {0}", plan.ServicePlanName);
}
}
}
public async Task<SubscribedSku[]> GetTenantLicenseDetailAsync(string accessToken)
{
var request = new RequestMessage
{
BearerToken = accessToken,
Endpoint = new Uri("http://graph.microsoft.com/v1.0/subscribedSkus"),
};
var response = await _httpClient.FetchAsync<SubscribedSkusResponse>(request);
return response.Value;
}
public static async Task<T> FetchAsync<T>(this HttpClient httpClient, RequestMessage request, Action<HttpResponseMessage, string> responseCallback) where T : class
{
request.Method = request.Method ?? HttpMethod.Get;
request.MediaType = request.MediaType ?? "application/json";
using (HttpRequestMessage message = new HttpRequestMessage(request.Method,
UrlHelper.AppendParameters(request.Params, request.Endpoint)))
{
if (!string.IsNullOrEmpty(request.BearerToken))
{
message.Headers.Authorization = new AuthenticationHeaderValue("Bearer",
request.BearerToken);
}
if (request.Headers != null)
{
foreach (KeyValuePair<string, string> header in request.Headers)
{
message.Headers.Add(header.Key, header.Value);
}
}
if (!string.IsNullOrEmpty(request.Content))
{
message.Content = new StringContent(request.Content, Encoding.UTF8,
request.MediaType);
}`
using (HttpResponseMessage response = await httpClient.SendAsync(message))
{
string json = await response.Content.ReadAsStringAsync();
if (responseCallback != null)
{
responseCallback?.Invoke(response, json);
}
if (response.IsSuccessStatusCode)
{
if (predictor != null)
{
json = predictor(JToken.Parse(json)).ToString();
}
return JsonConvert.DeserializeObject<T>(json);
}
else
{
throw new WebRequestException(response, json);
}
}
}
}
Firstly, try the same call for the new created user in Microsoft Graph Explorer to see if the same scene exists. If not, it means the there is nothing wrong with the new user.
Then debug your code and copy the graphToken into https://jwt.io/ and see if the Decoded result has one of the required Delegated permissions:Organization.Read.All, Directory.Read.All, Organization.ReadWrite.All, Directory.ReadWrite.All, Directory.AccessAsUser.All. Note that the "upn" should be the username of the new created user.
If the required permissions do not exist, you will need to assign permissions in the Azure AD app. See API permissions.
Perfect. Adding permission to the first party app has actually worked.
I'm trying to figure out where I went wrong.
services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new Info { Title = "MySite API", Version = "v1" });
options.OperationFilter<AuthorizeCheckOperationFilter>();
options.OperationFilter<AddSwaggerHeadersOperationFilter>();
options.AddSecurityDefinition("oauth2", new OAuth2Scheme
{
Type = "oauth2",
Flow = "implicit",
AuthorizationUrl = "authorization url",
TokenUrl = "token url",
Scopes = new Dictionary<string, string>()
{
{ "scope", "Scope" }
}
});
});
//Configure Method
app.UseSwagger();
app.UseSwaggerUI(options =>
{
options.SwaggerEndpoint("/swagger/v1/swagger.json", "MySite API V1");
options.OAuthClientId("MyClientId");
options.OAuthAppName("Swagger Api Calls");
//c.RoutePrefix = string.Empty;
});
//AuthorizeCheckOperationFilter
internal class AuthorizeCheckOperationFilter : IOperationFilter
{
public void Apply(Operation operation, OperationFilterContext context)
{
if (context.ApiDescription.TryGetMethodInfo(out var methodInfo))
{
var attributes = methodInfo.DeclaringType.GetTypeInfo().GetCustomAttributes(true);
if (attributes.OfType<AuthorizeAttribute>().Any())
{
operation.Responses.Add("401", new Response { Description = "Unauthorized" });
operation.Responses.Add("403", new Response { Description = "Forbidden" });
operation.Security = new List<IDictionary<string, IEnumerable<string>>>();
operation.Security.Add(new Dictionary<string, IEnumerable<string>>
{
{ "oauth2", new [] { "api1" } }
});
}
}
}
}
//Extra field
internal class AddSwaggerHeadersOperationFilter : IOperationFilter
{
public void Apply(Operation operation, OperationFilterContext context)
{
if (operation.Parameters == null)
operation.Parameters = new List<IParameter>();
operation.Parameters.Add(new NonBodyParameter
{
Name = "SomeField",
In = "header",
Type = "string",
Required = true,
Default = "some value"
});
}
}
Now when I open up the swagger page I get the Authorize button, to which I click and when I fill out the details there I get redirected to my Identity Website which logs me in and redirects right back to swagger. Swagger then says authorized, as if everything is fine.
Then I try to use an API which requires Bearer token to be passed and it doesn't pass it. I don't see it in the header and by my logs from the identity website nothing was passed.
Any idea why or how to fix this? I'm using Swashbuckle.AspNetCore 4.1 package.
You can add DocumentFilter :
public class SecurityRequirementsDocumentFilter : IDocumentFilter
{
public void Apply(SwaggerDocument document, DocumentFilterContext context)
{
document.Security = new List<IDictionary<string, IEnumerable<string>>>()
{
new Dictionary<string, IEnumerable<string>>()
{
{ "oauth2", new string[]{ "openid", "profile", "email" } },
}
};
}
}
And then register the filter in AddSwaggerGen function :
options.DocumentFilter<SecurityRequirementsDocumentFilter>();
Reference : https://github.com/domaindrivendev/Swashbuckle.AspNetCore/issues/603#issuecomment-368487641
I test with your code sample and it works as expected :
I implemented OAuth2 in my mvc web api project.I got the token but when I call the web api methods with this token the call will return 403 forbidden.I also called the same web api without the token it's working.Here is my token call:
public override Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
AccountLogin LogCredentials = new AccountLogin();
LogCredentials.UserName = context.UserName;
LogCredentials.Password = context.Password;
LogCredentials.IPAddress = "::1";
string webHost = Convert.ToString(WebConfigurationManager.AppSettings["webHost"]);
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { webHost });
ProviderLoginResponse providerLoginResponse = MembershipService.UserLogin(LogCredentials);
if (providerLoginResponse.LoginStatus != "Y")
{
context.SetError("invalid_grant", "The user name or password is incorrect.");
return Task.FromResult<object>(null);
}
var claims = new List<Claim>()
{
new Claim(ClaimTypes.Sid, Convert.ToString(providerLoginResponse.UserID)),
new Claim(ClaimTypes.Name, providerLoginResponse.UserName),
new Claim(ClaimTypes.Email, providerLoginResponse.UserEmail)
};
ClaimsIdentity oAuthIdentity = new ClaimsIdentity(claims,
Startup.OAuthOptions.AuthenticationType);
AuthenticationProperties properties = CreateProperties(providerLoginResponse);
AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, properties);
context.Validated(ticket);
return Task.FromResult<object>(null);
}
Here is my api method:
[HttpGet]
[Route("GetColumn")]
public HttpResponseMessage GetColumn(HttpRequestMessage request)
{
string tableName = "";
HttpResponseMessage response = null;
try
{
var clientList = _settingsService.GetColumns(tableName);
response = request.CreateResponse(HttpStatusCode.OK, new APIResponse { Status = true, Data = clientList, Message = Messages.Saved_Success });
}
catch (Exception ex)
{
response = request.CreateResponse(HttpStatusCode.OK, new APIResponse { Status = false, Data = null, Message = ex.Message });
}
return response;
}
My api call is :
function GetColumn(data, cb) {
var token = sessionStorage.getItem('accessToken');
var headers = {};
if (token) {
headers.Authorization = 'Bearer ' + token;
}
$.ajax({
type: 'GET',
url: "api/Settings/GetColumn",
headers: headers
}).done(function (data) {
cb(data);
}).fail(function (Res) {
cb(Res);
});
};
I also tried the postman by passing the Authorization token but still got the 403.I searched the web for this problem but nothing will solve my problem .Why it is behaving like this?
I'm develop a web api2 where I post json data.
The code of this api is:
public HttpResponseMessage Post(an_lavanderie an_lavanderie)
{
var response = new HttpResponseMessage();
if (!ModelState.IsValid)
{
response = Request.CreateErrorResponse(HttpStatusCode.NotFound, new Exception("modello non valido"));
}
bool creato = _repoLavanderie.CreaLavanderia(an_lavanderie);
if (creato == true)
{
response = Request.CreateResponse(HttpStatusCode.OK);
}
else
{
response = Request.CreateErrorResponse(HttpStatusCode.NotFound, new Exception("Errore nella creazione"));
}
return response;
}
This code write into db correctly.
My code to POST DATA is this:
var risultato = PostDataAsync();
and the function is
var lav1 = new Lavanderia()
{
rag_soc = "Ragione Sociale",
rag_soc2 = "Ragione sociale2",
indirizzo = "Via Crispi 27",
citta = "Ovada",
provincia = "AL",
isAttiva = "N",
portalkey = "sample string 1",
isPortalVisibile = "S",
cap = "15057"
};
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:56040/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var response = await client.PostAsJsonAsync("api/CreaLavanderia", lav1);
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
MessageBox.Show("Crezione effettuata correttamente");
}
else
{
MessageBox.Show("Creazione non effettuata");
}
}
return "";
Post operation is ok, but when await don't fire.
Is possible that the return Message from webapi is not correct?
Where is the problem?
Thanks.
Since you are using await and you're saying that it's not firing make sure that your method is marked with the keyword async.