How to send Get and Post request with POCO Library and OAuth2 - poco-libraries

I have a native window app program,and want access API of gitlab service,hope to get token using name and password with using POCO Library and OAuth2,but I don't know how to send Get and Post request to gitlab with OAuth2,and using POCO Library, please give me a example.
Here is the data that needs to be sent and received.
Requesting access token
POST request to /oauth/token with parameters:
{
"grant_type" : "password",
"username" : "user#example.com",
"password" : "secret"
}
Then, you'll receive the access token back in the response:
{
"access_token": "1f0af717251950dbd4d73154fdf0a474a5c5119adad999683f5b450c460726aa",
"token_type": "bearer",
"expires_in": 7200
}

First you need to create a HTTPRequest object like so:
Poco::Net::HTTPClientSession* session = Poco::Net::HTTPSessionFactory::defaultFactory().createClientSession(serverUri);
Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_POST, serverUri.getPathAndQuery(), Poco::Net::HTTPMessage::HTTP_1_1);
Then create a HTMLForm:
Poco::Net::HTMLForm form;
form.add("grant_type", "password");
form.add("client_id", "client token");
form.add("client_secret", "client secret");
form.add("username", "user#example.com");
form.add("password", "secret");
form.prepareSubmit(request);
Send the request and write the form data into the output stream of the request:
std::ostream& requestStream = session->sendRequest(request);
form.write(requestStream);
Get the response out of the session:
Poco::Net::HTTPResponse response;
std::istream& responseStream = session->receiveResponse(response);
std::stringstream rawJson;
Poco::StreamCopier::copyStream(responseStream, rawJson);
Parse the raw JSON:
Poco::JSON::Parser parser;
Poco::JSON::Object::Ptr authObj = parser.parse(rawJson).extract<Poco::JSON::Object::Ptr>();
Create a new session for next request and attach an authorization header to the request:
Poco::Net::HTTPClientSession* dataSession = Poco::Net::HTTPSessionFactory::defaultFactory().createClientSession(dataUri);
Poco::Net::HTTPRequest dataRequest(Poco::Net::HTTPRequest::HTTP_GET, dataUri.getPathAndQuery(), Poco::Net::HTTPMessage::HTTP_1_1);
dataRequest.add("Authorization", "Bearer " + authObj->get("access_token"));
dataSession->sendRequest(dataRequest);
Get the response and read the data from stream:
std::stringstream data;
Poco::Net::HTTPResponse dataResponse;
Poco::StreamCopier::copyStream(dataSession->receiveResponse(dataResponse), data);
Hope it helps or points into the right direction.

Related

How to pass form-urlencoded data in GET request with SWIFT 5

I'm using Swift 5 and attempting to get an access token from an API I'm developing using asp.net MVC. With Postman I set my request to GET, pass in some information in the body, and I get back an access token.
In XCode when I try this it gives me the error: "GET method must not have a body."
My Code:
func GetToken(email: String, password: String) {
let dataToSend = [
"grant_type": "password",
"username": email,
"password": password
]
let newData = try! JSONSerialization.data(withJSONObject: dataToSend, options: [])
var request = URLRequest(url: getNewTokenURL)
request.httpMethod = "Get"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = newData
URLSession.shared.dataTask(with: request) { (data, response, error) in
guard let data = data else {return}
do {
let myData = try JSONDecoder().decode(TokenResponse.self, from: data)
self.userToken = myData.accessToken
}
catch {
}
}.resume()
}
How do I perform the GET request with the data I need to send to it?
GET requests don't have a body. Parameters in a GET request are passed along with it's url as query parameters.
let url = URL(string: "https://www.example.com/getExample?sampleParam=sampleValue&anotherParam=anotherValue")
Edit: Also you need to give method in all caps. Since GET is the default you didn't have an issue.
Also if you are sure that the data is being passed as JSON then the method should be a POST method for that you just need to set the method of the request to POST as follows:
request.method = "POST"
Note: It's case sensitive.

Swagger Authorization bearer not send

I'm using Swagger Swashbuckle in a dotnet core 3.1 web api project and have trouble to send bearer authorization to the requests calls.
I've defined this in my ConfigureServices method:
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo() { Title = "MyApi", Version = "v1" });
// Set the comments path for the Swagger JSON and UI.
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
c.IncludeXmlComments(xmlPath);
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
Type = SecuritySchemeType.OAuth2,
Flows = new OpenApiOAuthFlows()
{
Password = new OpenApiOAuthFlow()
{
TokenUrl = new Uri("/api/Account/Login", UriKind.Relative),
}
},
In = ParameterLocation.Header,
Name = "Authorization",
Scheme = "Bearer",
});
c.AddSecurityRequirement(new OpenApiSecurityRequirement()
{
{
new OpenApiSecurityScheme()
{
Reference = new OpenApiReference()
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
},
Scheme = "Bearer",
Type = SecuritySchemeType.Http,
Name = "Bearer",
In = ParameterLocation.Header
}, new List<string>()
}
});
});
When running, I see the Authorize button that show the login dialog:
Once logged, the API routes show the locked padlock but when I try to use them, I see the call is done without the returned bearer:
curl -X GET "http://localhost:5000/api/Account" -H "accept: */*" -H "Authorization: Bearer undefined"
What's wrong with my definitions?
In the cURL request you can see: -H "Authorization: Bearer undefined".
This means that when Swagger-UI tries to get the token that will be added to the request header, it cannot be found.
Then, where the token cames from, and why Swagger-UI cannot found it? The token comes in the json returned from your login endpoint (/api/Account/Login).
You must be sure that returned json from your login endpoint repect the expected format for a OAuth password flow, as explained in the RFC6749 section 4.1.4 (Access Token Response).
From your login endpoint you must return a json response like this:
{
"access_token":"2YotnFZFEjr1zCsicMWpAA",
"token_type":"bearer"
}
It's a common mistake, that when you serialize the response from the controller you dont respect the json property names. In example: you can be returning a json like this:
{
"accessToken":"2YotnFZFEjr1zCsicMWpAA",
"tokenType":"bearer"
}
Where "accessToken" is not the same as "access_token" and so on.
This little difference causes that Swagger-UI cannot found the bearer token when it deserializes the returned json.
TIP: decorate the "AccessToken" property of your response object, so it will be serialized correctly.
[JsonPropertyName("access_token")]
[JsonProperty(PropertyName = "access_token")]
public string AccessToken { get; set; }
Although what is explained is the main point of your problem, I want to tell you that adding the security requirement globally is not the most correct way to do it. In this way you are protecting all the endpoints, regardless of whether they are decorated with the Authorize attribute or not.
In the startup you only must set a "Security Definition", and add an "OperationFilter" that handles the "security requirements". Then "SecurityRequirement" references the "SecurityDefinition", then you don't repeat the security definition configuration (Scheme, Type, Name, In, etc.) inside the security requirements as you are doing in your example.
Refer to this github post that shows you the correct way to do it.

LinkedIn returns 401 REST API when making request with HttpClient

I am unable to retrieve the profile details when making a call the /people endpoint.
using(HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token.TempToken);
client.DefaultRequestHeaders.Add("x-li-format", "json");
var response = await client.GetAsync("https://api.linkedin.com/v1/people/~?format=json");
if (response.IsSuccessStatusCode)
{
return "success";
}
return "failed";
}
I can confirm that the token is coming through at this point. And I have just successfully authorized before I pass the token to this code block.
Below is my request message:
{Method: GET, RequestUri: 'https://api.linkedin.com/v1/people/~?format=json', Version: 1.1, Content: , Headers:
{
Authorization: Bearer AQTgH0PIdKoSnCbbDaFhubm2q3wJcmv-qvxOqcd42qbdzfDja4DUj5Cs0YMk6RZ37Gv_0WWsrv24C9vhOG7d8M3IlPS9fez9DjwNu37U71PLiTzGPN-I4j1FsY7aJeMmf9I1v_XXXXXXXXXXXXXXXXX_3ADwlS6_a9
x-li-format: json
x-ms-request-root-id: 388de07b-44400de197c25bd0
x-ms-request-id: |388de07b-44400de197c25bd0.1.
Request-Id: |388de07b-44400de197c25bd0.1.
}}
Any assistance would be greatly appreciated.
Thanks
I was having the same issue for a few hours on 21-June. Fortunately it resolved itself so I'm assuming a linkedin api problem.

Web API not authorized when using JwtBearerAuthenticationOptions

I have taken section 2 from a walkthrough on how to authorize with jwt so that I can get an access token from my client and authorize them to use the api. However, I can't seem to get this to work. I keep on getting a 401 message from Postman accompanied by a:
{
"Message": "Authorization has been denied for this request."
}
Tutorial Link: http://bitoftech.net/2014/10/27/json-web-token-asp-net-web-api-2-jwt-owin-authorization-server/
The access token comes from an authorization service I have created in Java, so the first section of the tutorial does not apply to me.
JWT
{
"exp": 1489641048,
"user_name": "testuser",
"authorities": [
"USER"
],
"jti": "2dde11c3-2f06-496c-9b36-4dbf71cdc2e2",
"client_id": "webreport_service",
"scope": [
"USER"
]
}
Web API code snippet
public void ConfigureOAuth(IAppBuilder app)
{
var audience = "webreport_service";
// Api controllers with an [Authorize] attribute will be validated with JWT
app.UseJwtBearerAuthentication(
new JwtBearerAuthenticationOptions
{
AuthenticationMode = AuthenticationMode.Active,
AllowedAudiences = new[] { audience },
IssuerSecurityTokenProviders = new IIssuerSecurityTokenProvider[]
{
new SymmetricKeyIssuerSecurityTokenProvider("Any", "abc123")
}
});
}
It is slightly different from what is on the link in section 2, but that is because I don't base64 encode my secret and I also do not put the issuer in my jwt.
Postman
GET /api/protected HTTP/1.1
Host: localhost:54706
Authenticate: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0ODk2NDEyOTAsInVzZXJfbmFtZSI6InRlc3R1c2VyIiwiYXV0aG9yaXRpZXMiOlsiVVNFUiJdLCJqdGkiOiJlMDNkNWZmZC1hZWI4LTRkODctOGQ3My0zNjhjYjQ2ZDg2OWUiLCJjbGllbnRfaWQiOiJ3ZWJyZXBvcnRfc2VydmljZSIsInNjb3BlIjpbIlVTRVIiXX0.C4hivwA1VF-0GO0xCVUoDIheWQWlAcVWvAzChZTgrHY
Cache-Control: no-cache
Postman-Token: ff628109-d5f4-76e0-41c2-e0c7d377b93f
Any help would be greatly appreciated.
Thanks!
I think so check the following:
Firstly:
Check your secret base64 code. 'abc123' is true?
I'm check your token in jwt.io website on your secret code.
but Invalid Signature
Secondly:
Check your payload value.
What is 'iss' your jwt payload. / your issuer validate set 'Any'
What is 'aud' your jwt payload. / your audience validate set 'webreport_service'
Think about it.
Best regard

Asp.net Web Api Identity send bearer token in all request

I've a Web Api App with Identity 2 security. I can Login and get a response with bearer token like
{"access_token":"wiYvAyIgGggCmBBR36VwWZ[more...]",
"token_type":"bearer","expires_in":1209599,
"userName":"Ezeqiel",".issued":"Fri, 02 May 2014 15:23:27 GMT",
".expires":"Fri, 16 May 2014 15:23:27 GMT" }
The question is how can send this token to future request and how can redirect to login page when the user is not authenticated.
It depends on the type of client.
If its a aspnet type server side, you can put it in session/cache/httpcontext and send it with each request in the httpclient.
using (var apiClient = new HttpClient { BaseAddress = new Uri("http://localhost:54744/") })
{
var results = apiClient.PostAsJsonAsync("api/Authenticate/Token", loginModel).Result;
string token = results.Content.ReadAsAsync<string>().Result;
apiClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
}
If its a javascript spa type app, then on your login request from javascript you return that token from the server and you save it in storage or a variable and use it on each ajax request.
angular looks something like this
config.headers.Authorization = 'Bearer ' + $window.sessionStorage.token;
ajax looks something like this
beforeSend: function (xhr) {
xhr.setRequestHeader("Authorization", "Bearer $token")
}
Good luck

Resources