i want to consume a web service that require headers, body and parameters in future class
but the problem it shows an error "the named parameters isn't defined'
Future<http.Response> postLogin(String login, String password, String jwt) async{
final response = await http.post(Uri.encodeFull('$baseurl/mobile/login'),
headers: {
HttpHeaders.acceptHeader: 'application/json ; charset=utf-8',
HttpHeaders.contentTypeHeader:'application/x-www-form-urlencoded',
HttpHeaders.authorizationHeader :'Bearer $jwt',
},
body: bodyLoginToJson(login, password, token),
parameters: {
token, login
}
);
can someone help please
As mentioned by #jamesdlin, parameters is not a named parameter of the http class. The standard way of posting values using dart / flutter is a map past to the body parameter. Don't assume the terminology used in postman will be the same in dart.
Map<String, String> _headers = {
"Accept":"application/json"
};
var response = await http.post(LOGIN_URL, headers: _headers, body: {
"username": username,
"password": password,
// whatever other key values you want to post.
}).then((dynamic res) {
// ... Do something with the result.
});
Working with Angular 5 on in our app, we are authenticating through the Azure Active Directory(AAD), getting a bearer token to access the backend API. We are not having any success in the athentication call to the backend api, getting a 401 unauthrized. Both App and Api is hosted in Azure. Any help would be appreciated in troubleshooting this issue:
The App service Registration on AAD:
Angular App (using the adal-angular5 1.0.36 library):
Application ID: aaaaa-aaaaa-aaaaa-aaaaa-aaaaa
Object ID: bbbbbb-bbbbb-bbbb-bbbbb-bbbbbb
App ID URI: https://frontendapp.azurewebsites.net
Home Page URL: https://homepage.frontendapp.com
Backend API (.Net 4.7):
Application ID: cccccc-cccccc-cccccc-cccccc-cccccc
Object ID: dddddd-ddddd-ddddd-dddddd-dddddd
App ID URI: https://backendapi.azurewebsites.net
Home Page URL: https://homepage.backendapi.com
App side
config for adal-angular5 on the Angular App:
config: adal.Config = {
tenant: 'common',
clientId: 'aaaaa-aaaaa-aaaaa-aaaaa-aaaaa',
postLogoutRedirectUri: window.location.origin,
endpoints: {
ApiUri: "https://homepage.backendapi.com",
}
};
Call to get the bearer token:
this.adal5Service.acquireToken("https://backendapi.azurewebsites.net")
call to the api
we verified the options contains the header which has the bearer token:
this.adal5HttpService.get('/api/hello', options);
On the API side
we are using the Microsoft Owin library (Microsoft.Owin 4.0.0 nuget package),
API startup:
public partial class Startup
{
/// <summary>
/// Initializes OWIN authentication.
/// </summary>
/// <param name="app">Web API AppBuilder</param>
public void Configuration(IAppBuilder app)
{
if (app == null)
{
throw new ArgumentNullException("app");
}
app.UseWindowsAzureActiveDirectoryBearerAuthentication(
new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
Tenant = "common",
Audience = "https://backendapi.azurewebsites.net"
});
}
}
API side controler
[HttpGet]
[Authorize]
[Route("hello")]
public string GetHello()
{
try
{
var result = "we hit it yay!!!!!!!!!!!!!!!";
return result;
}
catch (Exception ex)
{
var msg = "not hit saddd.....";
var error = new Exception(msg, ex);
throw error;
}
}
With the [Authorize] attribute we are getting a 401 unauthorized, with no additional error message.
Without the [Authorize] attribute we are hitting the Controller method just fine and getting the return results.
I was able to confirm the bearer token that's sent from the App is indeed the bearer token we get in the header in our Api. I can't figure out why we are getting the unauthorized.
Is the config setting in correct on the APP or the API side?
Is there additional configuration needed in Azure?
Any help would be appreciate it!
I have some endpoints in the API - /user/login, /products.
In Swagger UI I post email and password to /user/login and as a response I receive a token string.
Then, I can copy the token from the response and want to use it as Authorization header value in requests to all urls if it's present, and to /products as an example.
Should I create a text input manually somewhere on the Swagger UI page, then put the token there and somehow inject in the requests or are there tools to manage it in a better way?
You can add a header parameter to your request, and Swagger-UI will show it as an editable text box:
swagger: "2.0"
info:
version: 1.0.0
title: TaxBlaster
host: taxblaster.com
basePath: /api
schemes:
- http
paths:
/taxFilings/{id}:
get:
parameters:
- name: id
in: path
description: ID of the requested TaxFiling
required: true
type: string
- name: auth
in: header
description: an authorization header
required: true
type: string
responses:
200:
description: Successful response, with a representation of the Tax Filing.
schema:
$ref: "#/definitions/TaxFilingObject"
404:
description: The requested tax filing was not found.
definitions:
TaxFilingObject:
type: object
description: An individual Tax Filing record.
properties:
filingID:
type: string
year:
type: string
period:
type: integer
currency:
type: string
taxpayer:
type: object
You can also add a security definition with type apiKey:
swagger: "2.0"
info:
version: 1.0.0
title: TaxBlaster
host: taxblaster.com
basePath: /api
schemes:
- http
securityDefinitions:
api_key:
type: apiKey
name: api_key
in: header
description: Requests should pass an api_key header.
security:
- api_key: []
paths:
/taxFilings/{id}:
get:
parameters:
- name: id
in: path
description: ID of the requested TaxFiling
required: true
type: string
responses:
200:
description: Successful response, with a representation of the Tax Filing.
schema:
$ref: "#/definitions/TaxFilingObject"
404:
description: The requested tax filing was not found.
definitions:
TaxFilingObject:
type: object
description: An individual Tax Filing record.
properties:
filingID:
type: string
year:
type: string
period:
type: integer
currency:
type: string
taxpayer:
type: object
The securityDefinitions object defines security schemes.
The security object (called "security requirements" in Swagger–OpenAPI), applies a security scheme to a given context. In our case, we're applying it to the entire API by declaring the security requirement a top level. We can optionally override it within individual path items and/or methods.
This would be the preferred way to specify your security scheme; and it replaces the header parameter from the first example. Unfortunately, Swagger-UI doesn't offer a text box to control this parameter, at least in my testing so far.
In ASP.NET Web API, the simplest way to pass-in a header on Swagger UI is to implement the Apply(...) method on the IOperationFilter interface.
Add this to your project:
public class AddRequiredHeaderParameter : IOperationFilter
{
public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
{
if (operation.parameters == null)
operation.parameters = new List<Parameter>();
operation.parameters.Add(new Parameter
{
name = "MyHeaderField",
#in = "header",
type = "string",
description = "My header field",
required = true
});
}
}
In SwaggerConfig.cs, register the filter from above using c.OperationFilter<T>():
public static void Register()
{
var thisAssembly = typeof(SwaggerConfig).Assembly;
GlobalConfiguration.Configuration
.EnableSwagger(c =>
{
c.SingleApiVersion("v1", "YourProjectName");
c.IgnoreObsoleteActions();
c.UseFullTypeNameInSchemaIds();
c.DescribeAllEnumsAsStrings();
c.IncludeXmlComments(GetXmlCommentsPath());
c.ResolveConflictingActions(apiDescriptions => apiDescriptions.First());
c.OperationFilter<AddRequiredHeaderParameter>(); // Add this here
})
.EnableSwaggerUi(c =>
{
c.DocExpansion(DocExpansion.List);
});
}
In ASP.NET Core 2 Web API, using Swashbuckle.AspNetCore package 2.1.0, implement a IDocumentFilter:
SwaggerSecurityRequirementsDocumentFilter.cs
using System.Collections.Generic;
using Swashbuckle.AspNetCore.Swagger;
using Swashbuckle.AspNetCore.SwaggerGen;
namespace api.infrastructure.filters
{
public class SwaggerSecurityRequirementsDocumentFilter : IDocumentFilter
{
public void Apply(SwaggerDocument document, DocumentFilterContext context)
{
document.Security = new List<IDictionary<string, IEnumerable<string>>>()
{
new Dictionary<string, IEnumerable<string>>()
{
{ "Bearer", new string[]{ } },
{ "Basic", new string[]{ } },
}
};
}
}
}
In Startup.cs, configure a security definition and register the custom filter:
public void ConfigureServices(IServiceCollection services)
{
services.AddSwaggerGen(c =>
{
// c.SwaggerDoc(.....
c.AddSecurityDefinition("Bearer", new ApiKeyScheme()
{
Description = "Authorization header using the Bearer scheme",
Name = "Authorization",
In = "header"
});
c.DocumentFilter<SwaggerSecurityRequirementsDocumentFilter>();
});
}
In Swagger UI, click on Authorize button and set value for token.
Result:
curl -X GET "http://localhost:5000/api/tenants" -H "accept: text/plain" -H "Authorization: Bearer ABCD123456"
Also it's possible to use attribute [FromHeader] for web methods parameters (or properties in a Model class) which should be sent in custom headers. Something like this:
[HttpGet]
public ActionResult Products([FromHeader(Name = "User-Identity")] string userIdentity)
At least it works fine for ASP.NET Core 2.1 and Swashbuckle.AspNetCore 2.5.0.
Here's a simpler answer for the ASP.NET Core Web Api/Swashbuckle combo, that doesn't require you to register any custom filters. Third time's a charm you know :).
Adding the code below to your Swagger config will cause the Authorize button to appear, allowing you to enter a bearer token to be sent for all requests. Don't forget to enter this token as Bearer <your token here> when asked.
Note that the code below will send the token for any and all requests and operations, which may or may not be what you want.
services.AddSwaggerGen(c =>
{
//...
c.AddSecurityDefinition("Bearer", new ApiKeyScheme()
{
Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"",
Name = "Authorization",
In = "header",
Type = "apiKey"
});
c.AddSecurityRequirement(new Dictionary<string, IEnumerable<string>>
{
{ "Bearer", new string[] { } }
});
//...
}
Via this thread.
This is how I achieved it in .NET 6
public class AddCustomHeaderParameter
: IOperationFilter
{
public void Apply(
OpenApiOperation operation,
OperationFilterContext context)
{
if (operation.Parameters is null)
{
operation.Parameters = new List<OpenApiParameter>();
}
operation.Parameters.Add(new OpenApiParameter
{
Name = "Custom Header",
In = ParameterLocation.Header,
Description = "Custom Header description",
Required = true,
});
}
}
And finally
services.AddSwaggerGen(c =>
{
c.OperationFilter<AddCustomHeaderParameter>();
});
For those who use NSwag and need a custom header:
app.UseSwaggerUi3(typeof(Startup).GetTypeInfo().Assembly, settings =>
{
settings.GeneratorSettings.IsAspNetCore = true;
settings.GeneratorSettings.OperationProcessors.Add(new OperationSecurityScopeProcessor("custom-auth"));
settings.GeneratorSettings.DocumentProcessors.Add(
new SecurityDefinitionAppender("custom-auth", new SwaggerSecurityScheme
{
Type = SwaggerSecuritySchemeType.ApiKey,
Name = "header-name",
Description = "header description",
In = SwaggerSecurityApiKeyLocation.Header
}));
});
}
Swagger UI will then include an Authorize button.
I ended up here because I was trying to conditionally add header parameters in Swagger UI, based on my own [Authentication] attribute I added to my API method. Following the hint that #Corcus listed in a comment, I was able to derive my solution, and hopefully it will help others.
Using Reflection, it's checking if the method nested down in apiDescription has the desired attribute (MyApiKeyAuthenticationAttribute, in my case). If it does, I can append my desired header parameters.
public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription) {
if (operation.parameters == null)
operation.parameters = new List<Parameter>();
var attributes = ((System.Web.Http.Controllers.ReflectedHttpActionDescriptor)
((apiDescription.ActionDescriptor).ActionBinding.ActionDescriptor)).MethodInfo
.GetCustomAttributes(false);
if(attributes != null && attributes.Any()) {
if(attributes.Where(x => x.GetType()
== typeof(MyApiKeyAuthenticationAttribute)).Any()) {
operation.parameters.Add(new Parameter {
name = "MyApiKey",
#in = "header",
type = "string",
description = "My API Key",
required = true
});
operation.parameters.Add(new Parameter {
name = "EID",
#in = "header",
type = "string",
description = "Employee ID",
required = true
});
}
}
}
Update for OpenAPI 3, library Swashbuckle.AspNetCore. Correct code sample is provifded by this source: https://codeburst.io/api-security-in-swagger-f2afff82fb8e
For use with JWT Bearer correct code is:
services.AddSwaggerGen(c =>
{
// configure SwaggerDoc and others
// add JWT Authentication
var securityScheme = new OpenApiSecurityScheme
{
Name = "JWT Authentication",
Description = "Enter JWT Bearer token **_only_**",
In = ParameterLocation.Header,
Type = SecuritySchemeType.Http,
Scheme = "bearer", // must be lower case
BearerFormat = "JWT",
Reference = new OpenApiReference
{
Id = JwtBearerDefaults.AuthenticationScheme,
Type = ReferenceType.SecurityScheme
}
};
c.AddSecurityDefinition(securityScheme.Reference.Id, securityScheme);
c.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{securityScheme, new string[] { }}
});
}
I've seen one article with similar code for OpenAPI 2 and lost many hours because that example missed Reference definition. This resulted that Swashbuckle generated incorrect definitions and missed to include Authorizeation header. So check carefully the OpenAPI version you use.
Golang/go-swagger example: https://github.com/go-swagger/go-swagger/issues/1416
// swagger:parameters opid
type XRequestIdHeader struct {
// in: header
// required: true
XRequestId string `json:"X-Request-Id"`
}
...
// swagger:operation POST /endpoint/ opid
// Parameters:
// - $ref: #/parameters/XRequestIDHeader
If you are working with Nest.js, it can be achieved by adding addBearerAuth() while setting up the swagger(probably in the main.ts).
...........
const config = new DocumentBuilder()
.setTitle('Your title')
.setDescription('Your description')
.setVersion('1.0')
.addBearerAuth() // Add here
.build();
const document = SwaggerModule.createDocument(app, config);
SwaggerModule.setup('api', app, document);
...........
With this added, we can pass in the Bearer token from the Swagger UI as:
PS: You have to use Authguard in respective controllers to protect your routes.
Just updating this for Asp.Net Core 6 web api and Swashbuckle.AspNetCore 6.4.0. It was surprisingly easy. In my case the header is required for all action methods so I have Required true.
One, create a Swashbuckle.AspNetCore.SwaggerGen.IOperationFilter:
public class IMyCustomFilter : IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
if (operation.Parameters == null)
operation.Parameters = new List<OpenApiParameter>();
operation.Parameters.Add(new OpenApiParameter()
{
Name= "MyCustomHeader",
In=ParameterLocation.Header,
Required=true
});
}
}
Two, tell Swagger to use it when you are configuring services:
builder.Services.AddSwaggerGen(config =>
{
//this causes Swagger to add an input so you can to add the value to header when you are executing an api method.
config.OperationFilter<IMyCustomFilter>();
});
Three, invoke Swagger as usual:
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
DISCLAIMER: this solution is not using Header.
If someone is looking for a lazy-lazy manner (also in WebApi), I'd suggest:
public YourResult Authorize([FromBody]BasicAuthCredentials credentials)
You are not getting from header, but at least you have an easy alternative.
You can always check the object for null and fallback to header mechanism.
In Feathers Swagger, to show the Authorize button on the top right in this case for BearerAuth, your config declaration must be done as such:
{
...config, // other config parameters
specs: {
info: {
title: 'My API',
description: 'My API Documentation',
version: '2.0',
},
components: {
securityDefinitions: {
BasicAuth: {
type: 'basic'
},
BearerAuth: {
type: "http",
scheme: "bearer",
bearerFormat: "JWT"
}
},
},
security: {
BearerAuth: []
},
},
}
Result
I'm using Microsoft Owin and ASP.NET WebApi for authentication and authorization process for my client application. Also the authentication server is secured by HTTPS. I've read a few articles about using Microsoft Owin, one of them which I've chosen to implement is:
Token Based Authentication using ASP.NET Web API 2, Owin, and Identity
There are some differences between my project and that implementation:
I need to identify my client in case the request is sent by my application on the mobile phone, not any other devices or tools like Fiddler. I think one the options could be sending an application id by each request from the mobile application. But I don't know how and where should I verify the requests in authentication server application. This is really important for registering users:
[AllowAnonymous]
[Route("Register")]
public async Task<IHttpActionResult> Register(UserModel userModel)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
IdentityResult result = await _repo.RegisterUser(userModel);
IHttpActionResult errorResult = GetErrorResult(result);
if (errorResult != null)
{
return errorResult;
}
return Ok();
}
I don't want to let unreliable devices, i.e. the clients except the mobile application, to call this method.
I need to let anonymous users to buy some products from the website, but I don't know what is the best practice to issue token for anonymous users without doing authentication.
If you want to identify your client and authorize it you can override the method ValidateClientAuthentication.
In Taiseer's example you have linked you will find some code:
public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
context.Validated();
}
and a note which says:
As you notice this class inherits from class
“OAuthAuthorizationServerProvider”, we’ve overridden two methods
“ValidateClientAuthentication” and “GrantResourceOwnerCredentials”.
The first method is responsible for validating the “Client”, in our
case we have only one client so we’ll always return that its validated
successfully.
If you want to validate the client you have to put some logic in there.
Normally you would pass a clientId and a clientSecret in the header of your http request, so that you can validate the client's request with some database parameters, for example.
public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
string clientId = string.Empty;
string clientSecret = string.Empty;
if (!context.TryGetBasicCredentials(out clientId, out clientSecret))
{
context.TryGetFormCredentials(out clientId, out clientSecret);
}
if (context.ClientId == null)
{
context.SetError("invalid_client", "Client credentials could not be retrieved through the Authorization header.");
context.Rejected();
return;
}
try
{
// You're going to check the client's credentials on a database.
if (clientId == "MyApp" && clientSecret == "MySecret")
{
context.Validated(clientId);
}
else
{
// Client could not be validated.
context.SetError("invalid_client", "Client credentials are invalid.");
context.Rejected();
}
}
catch (Exception ex)
{
string errorMessage = ex.Message;
context.SetError("server_error");
context.Rejected();
}
return;
}
In the sample above you will try to extract the client credentials sent in the header of your request:
if (!context.TryGetBasicCredentials(out clientId, out clientSecret))
{
context.TryGetFormCredentials(out clientId, out clientSecret);
}
and validated them:
// You're going to check the client's credentials on a database.
if (clientId == "MyApp" && clientSecret == "MySecret")
{
context.Validated(clientId);
}
if the client is sending a wrong request header you need to reject the request:
context.SetError("invalid_client", "Client credentials are invalid.");
context.Rejected();
The method ValidateClientAuthentication is processed before GrantResourceOwnerCredentials. This way you can extend it and pass GrantResourceOwnerCredentials some extra information you might need there.
In one of my applications I've created a class:
class ApplicationClient
{
public string Id { get; set; }
public string Name { get; set; }
public string ClientSecretHash { get; set; }
public OAuthGrant AllowedGrant { get; set; }
public DateTimeOffset CreatedOn { get; set; }
}
which I use in ValidateClientAuthentication right after I've checked the clientId and the secret are ok:
if (clientId == "MyApp" && clientSecret == "MySecret")
{
ApplicationClient client = new ApplicationClient();
client.Id = clientId;
client.AllowedGrant = OAuthGrant.ResourceOwner;
client.ClientSecretHash = new PasswordHasher().HashPassword("MySecret");
client.Name = "My App";
client.CreatedOn = DateTimeOffset.UtcNow;
context.OwinContext.Set<ApplicationClient>("oauth:client", client);
context.Validated(clientId);
}
As you can see here
context.OwinContext.Set<ApplicationClient>("oauth:client", client);
I am setting a Owin variable which I can read later on. In your GrantResourceOwnerCredentials now you can read that variable in case you need it:
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
ApplicationClient client = context.OwinContext.Get<ApplicationClient>("oauth:client");
...
}
Now, if you want to fetch the bearer token - which you're going to use for all the secure API calls - you need to encode your clientId and clientSecret (base64) and pass it in the header of the request:
An ajax request with jquery would look something like this:
var clientId = "MyApp";
var clientSecret = "MySecret";
var authorizationBasic = $.base64.btoa(clientId + ':' + clientSecret);
$.ajax({
type: 'POST',
url: '<your API token validator>',
data: { username: 'John', password: 'Smith', grant_type: 'password' },
dataType: "json",
contentType: 'application/x-www-form-urlencoded; charset=utf-8',
xhrFields: {
withCredentials: true
},
headers: {
'Authorization': 'Basic ' + authorizationBasic
},
beforeSend: function (xhr) {
},
success: function (result) {
var token = result.access_token;
},
error: function (req, status, error) {
alert(error);
}
});
As you can see I've also added the username and password - with the grant type - in the body of the request:
data: { username: 'John', password: 'Smith', grant_type: 'password' }
so that the server will be able to validate the client (clientId + clientSecret) and the user (username + password).
If the request is successful you should get back a valid token:
oAuth.Token = result.access_token;
which you can store somewhere for the following requests.
Now you can use this token for all the requests to the api:
$.ajax({
type: 'GET',
url: 'myapi/fetchCustomer/001',
data: { },
dataType: "json",
headers: {
'Authorization': 'Bearer ' + oAuth.Token
},
success: function (result) {
// your customer is in the result.
},
error: function (req, status, error) {
alert(error);
}
});
Another thing you might want to add to your API during the startup is SuppressDefaultHostAuthentication:
config.SuppressDefaultHostAuthentication();
this is an extension method of HttpConfiguration. Since you're using bearer tokens you want to suppress the standard cookie-based authentication mechanism.
Taiseer has written another series of articles which are worth reading where he explains all these things.
I have created a github repo where you can see how it works.
The Web API is self-hosted and there are two clients: jQuery and Console Application.