swagger not showing any data - asp.net-web-api2

I am currently using below version of swagger
<package id="Swashbuckle.Core" version="5.5.3" targetFramework="net45" />
if I hit the swagger api from postman I get the data
But if I open it from browser, the browser becomes unresponsive
What can I do to make swagger-ui to work??
I tried the owin solution provide in the faq, also tried disabling the validator but did not worked. Below is my swagger configuration :
config.EnableSwagger(c =>
{
c.SingleApiVersion("v1", "ColloSys.Webapi");
c.ResolveConflictingActions(x => x.First());
c.RootUrl(req =>
req.RequestUri.GetLeftPart(UriPartial.Authority) +
req.GetRequestContext().VirtualPathRoot.TrimEnd('/'));
}).EnableSwaggerUi(x =>
{
x.DisableValidator();
});
FYI: I am using it with OWIN, and my web-api has bearer token authentication implementation (if that matters)
** EDIT **
if I open it in firefox it give me error about unresponsive script

Related

ASP.NET Core 3.1 CORS error in VS for Mac

Initially, I started to develop my project on PC and now I'm trying to run it on Mac. When my front end tries to reach my web API endpoint, I'm getting the following error:
Failed to load resource: Origin https://localhost:3000 is not allowed by Access-Control-Allow-Origin
The thing is that it works perfectly on Windows, but doesn't work on Mac.
My code to enable CORS:
builder.UseCors(x => x
.WithOrigins(new string[] { "https://localhost:3000" })
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
How to solve this issue?
In "ConfigureServices" of your startup.cs add this (it is a different syntax from yours):
services.AddCors(o => o.AddPolicy("AllowSpecificOrigins", builder =>
{
builder..WithOrigins("https://localhost:3000")
.AllowAnyMethod()
.AllowAnyHeader();
}));
In "Config" change yours to this:
app.UseCors("AllowSpecificOrigins");
and place it after UseRouting but before UseAuthorization.
Also remove all Cors attributes from all controller actions.
Okay, it turned out that I had to "trust" the dev certificate created by dotnet core command. I opened my backend URL from browser (https://localhost:44372), clicked "Proceed" when the "site is unsafe" prompt appeared and only after that my front end (https://localhost:3000) was able to reach it.

URL Rewrite exceptions for Blazor WebAssembly Hosted deployment

During development, i have used Swagger on the server side of my Blazor WebAssembly App. Always launching (debug) using kestrel instead of IIS Express.
Routing worked as expected, all my component routed properly and if i manually typed /swagger, i got to the swagger page. All good.
We have deployed under IIS on our pre-prod servers, the Server side and Blazor WebAssembly App (client) work as expected and are usable, however, my /swagger url gets rewritten (I assume) to go somewhere in my App instead of letting it go to Swagger, obviously there isn't any component that answers to /swagger.
My only guess is that, when hosted on IIS, the aspnet core app takes care of telling IIS what to rewrite and how (similar to the configs that could be provided thru a web.config for a "Standalone" deployment.)
I can't find how to specify exceptions, I've been following the doc at
https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/blazor/webassembly?view=aspnetcore-3.1#iis
Any idea how i could add an exception for /swagger ?
EDIT:
Turns out it works without issues in Chrome, only Firefox has the unwanted behavior. If i clear my cache, or use Incognito mode, the issue does not happen in Firefox. So, it seems that Firefox caches some stuff and tries to send my URL input to the Blazor Wasm instead of going thru to the server. I will debug some more with the dev tools and fiddler open to try and figure it out, will report back.
Turns out there this is part of the service-worker.js file that is published. It is different in dev than what gets published (which makes sense).
During my debugging i was able to reproduce the issue on all browsers (Edge, Chrome and Firefox), regardless of being in Incognito/Private mode or not.
Once the service-worker is running, it handles serving requests from cache/index.html of the Blazor WebAssembly app.
If you go into your Blazor WebAssembly Client "wwwroot" folder, you'll find a service-worker.js and a service-worker.published.js. In the service-worker.published.js, you will find a function that looks like this :
async function onFetch(event) {
let cachedResponse = null;
if (event.request.method === 'GET') {
// For all navigation requests, try to serve index.html from cache
// If you need some URLs to be server-rendered, edit the following check to exclude those URLs
const shouldServeIndexHtml = event.request.mode === 'navigate'
&& !event.request.url.includes('/connect/')
&& !event.request.url.includes('/Identity/');
const request = shouldServeIndexHtml ? 'index.html' : event.request;
const cache = await caches.open(cacheName);
cachedResponse = await cache.match(request);
}
return cachedResponse || fetch(event.request);
}
Simply following the instructions found in the code comments is gonna fix the issue. So we ended up adding an exclusion for "/swagger" like so :
&& !event.request.url.includes('/swagger')
Hopefully this post is useful for people who are gonna want to serve things outside of the service worker, not only Swagger.
Do you have UseSwagger first in your Startup.Configure method?
public static void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseSwagger();
app.UseSwaggerUI(c =>
c.SwaggerEndpoint("/swagger/v1/swagger.json", "YourAppName V1")
);
In Startup.ConfigureServices I have the Swagger code last.
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddSwaggerGen(c =>
c.SwaggerDoc(
name: "v1",
info: new OpenApiInfo
{
Title = "YourAppName",
Version = "V1",
}));
}
This is working just fine for us.
Note: You must navigate to https://yourdomain/swagger/index.html

Getting 401 when calling ASP.NET Core 2.1 API. Is this a CORS issue?

I've been trying to resolve a 401 error for the past couple days without any success.
ASP.NET Core 2.1 API hosted behind IIS. I'm trying to access the API with windows authorisation but I'm being challenged with a login prompt. If I don't enter a username and password I get a 401 error (screenshot attached). I've followed all the articles I could find and believe I have CORS configured correctly.
Based on the screenshot does this look like a CORS issue? I'm testing via swagger and am calling from what I believe is the same domain. Does anyone have any suggestions regarding what the issue may be?
From what I see in this screenshot, everything works fine. 401 is a desirable error in this scenario, it is also proof that you don't have any problems with CORS because the API responds to your requests in an adequate way.
To break through to Api you should focus on the "Response Headers" section in which the type of authentication is defined as BEARER.
From this we can conclude that authentication is token based and in practice works as follows:
By correctly logging in through Windows Authentication, WebAPI provides a response token in header that identifies you as a user.
In order to have access to API, you should store this token locally, and then make use of it by adding it to header section of each request.
To learn more about token based authentication in swagger, check
https://swagger.io/docs/specification/authentication/bearer-authentication/
To understand how tokens works, check https://jwt.io/
Below is an example of how to achieve the intended goal by configuring swagger in the startup class of asp net core application.
public void ConfigureServices(IServiceCollection services)
{
//other code removed for brevity
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new Info { Title = "My App API", Version = "v1" });
c.CustomSchemaIds((type) => type.FullName);
c.DescribeAllEnumsAsStrings();
c.DescribeAllParametersInCamelCase();
c.EnableAnnotations();
c.OperationFilter<FormFileOperationFilter>();
var apiXmlDocFileName = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var apiXmlDocFilePath = Path.Combine(AppContext.BaseDirectory, apiXmlDocFileName);
c.IncludeXmlComments(apiXmlDocFilePath);
c.AddFluentValidationRules();
c.AddSecurityDefinition("Bearer", new ApiKeyScheme() //this is desireable line
{
Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"",
Name = "Authorization",
In = "header"
});
c.AddSecurityRequirement(new Dictionary<string, IEnumerable<string>> { { "Bearer", Enumerable.Empty<string>() } });
});
}
After implementing this you will be able to add the token to all requests directly from the swagger UI.
You can also achieve the intended goal using Postman
https://learning.getpostman.com/docs/postman/sending-api-requests/authorization/
Hope it Helps.

How to configure Swagger in Web API 2 to POST OAuth2 authentication request?

I have recently started a Web API 2 project in Visual Studio 2012 using OWIN middleware to authenticate users with OAuth2. I incorporated token based authentication as outlined on this tutorial (Token Based Authentication). The authentication part works great. I have added some testing API methods and I wanted to hook up Swagger for my API documentation. I got that part working too, with the exception that the API calls from Swagger fail on authorization.
After research, I found Erik Dahl's post about how to hook up Swagger to OWIN middleware. After I configured my Swagger according to the post, I now see the authenticate buttons on the Swagger UI next to each API method. However, when trying to authenticate, the authentication within Swagger is done using a GET request. The authentication on the web API though requires it to be POST request. Is it possible to configure Swagger make the authentication request a POST? If not, should I allow my API to accept GET requests for token authentication? What would be the best approach to make this work?
Note: The request still hits my authentication logic, but the client_id and client_secret are not passed in a GET request, only in a POST request.
Here's my Swagger config:
httpConfig
.EnableSwagger(c =>
{
c.SingleApiVersion("v1", "Sample API");
c.ApiKey("token")
.Description("API Key Authentication")
.Name("Bearer")
.In("header");
c.OAuth2("oauth2")
.AuthorizationUrl("/oauth/token")
.Flow("implicit")
.Description("OAuth2 authentication")
.Scopes(scopes =>
{
scopes.Add("sampleapi", "Sample API");
});
c.OperationFilter<AssignOAuth2SecurityRequirements>();
})
.EnableSwaggerUi(c =>
{
c.EnableOAuth2Support(
clientId: "Sample_App",
clientSecret: "xxxxx",
realm: "test-realm",
appName: "Swagger UI");
});
And here's my OAuth config:
app.CreatePerOwinContext<ApiClientRepo>(ApiClientRepo.Create);
app.CreatePerOwinContext<MeetingRegistrantRepo>(MeetingRegistrantRepo.Create);
OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
{
//For Dev enviroment only (on production should be AllowInsecureHttp = false)
AllowInsecureHttp = true,
TokenEndpointPath = new PathString("/oauth/token"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
Provider = new CustomOAuthProvider(),
AccessTokenFormat = new CustomJwtFormat("http://localhost:51071"),
RefreshTokenProvider = new SimpleRefreshTokenProvider()
};
// OAuth 2.0 Bearer Access Token Generation
app.UseOAuthAuthorizationServer(OAuthServerOptions);
No, I would not change the authentication method from POST to GET just to satisfy Swagger.
I found another article which should help you do what you want to do here : http://danielwertheim.se/use-identityserver-in-swaggerui-to-consume-a-secured-asp-net-webapi/
It wold be worth to try it that way. Don't forget that changing from POST to GET means you can no longer pass the parameters in the body of the request and you will instead have to do it in the URL of the request and that makes the whole thing insecure.
Yes, the ClientID and ClientSecret will still be part of the Authorization Header, but still do not open yourself up to stuff like this. Swagger should not dictate the architecture of your API so don't go there.

JSONP - POST method in Sench Touch 2.1

With GET method, i easily get this reponse. But POST method i don't get it.
Ext.data.JsonP.request({
url: 'http://otherdomain/test_json_post',
method: 'POST',
type:'jsonp',
scope: this,
callbackkey: 'callback',
success: function(result) {
console.log(result);
//Your success function here...
}
});
What i wrong?
You cannot call any webservice from your browser because of security reasons so either you have to use JSONP proxy on app side or you have to enable CORS on your server side. If you are planning to build this as app then you don't have to do this, all you have to do is change security setting of your browser when you are testing. More details here : How to use json proxy to access remote services during development
Yes,it worked! ^^ Sencha Touch is a client-side(a Mobile Web App) or builded it localhost, it will have CORS - a browser policy security - related to your using ajax in it. So, I configed all api in my PHP server by add 2 code rows:
function yourAPI
{
//CORS open
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Headers: X-Requested-With');
....
{enter your code here}
}
Thank for Rob's help! Hope you have similar problem fix error successfully.