Web API with OAUTH using Swagger / Swashbuckle
I got my solution. This this is powerful, just not 100% straight forward to configure.
Here are the steps I took:
Install the NuGet Package, I used PM> Install-Package Swashbuckle -Version 4.1.0
but the link is at https://www.nuget.org/packages/Swashbuckle/ and I would recommend getting the latest, but I know 4.1.0 worked. EDIT I just updated to 5.X and it broke it. 4.1.0 works but latest did not. I haven't researched more into why yet.
Once you install this, your are almost done.
The install will create a SwaggerConfig.cs file. This is the code I used (Copied from github master)
public class SwaggerConfig
{
public static void Register()
{
Swashbuckle.Bootstrapper.Init(GlobalConfiguration.Configuration);
SwaggerSpecConfig.Customize(c =>
{
c.IgnoreObsoleteActions();
//c.SupportMultipleApiVersions(
// new[] { "1.0", "2.0" },
// ResolveVersionSupportByRouteConstraint);
//c.PolymorphicType<Animal>(ac => ac
// .DiscriminateBy(a => a.Type)
// .SubType<Kitten>());
c.OperationFilter<AddStandardResponseCodes>();
c.OperationFilter<AddAuthResponseCodes>();
c.OperationFilter<AddOAuth2Scopes>();
//c.IncludeXmlComments(GetXmlCommentsPath());
c.ApiInfo(new Info
{
Title = "Swashbuckle Dummy",
Description = "For testing and experimenting with Swashbuckle features",
Contact = "[email protected]"
});
c.Authorization("oauth2", new Authorization
{
Type = "oauth2",
Scopes = new List<Scope>
{
new Scope { ScopeId = "test1", Description = "test1" },
new Scope { ScopeId = "test2", Description = "test2" }
},
GrantTypes = new GrantTypes
{
ImplicitGrant = new ImplicitGrant
{
LoginEndpoint = new LoginEndpoint
{
Url = "https://your.Oauth.server/Authorize"
},
TokenName = "access_token"
}
}
});
});
SwaggerUiConfig.Customize(c =>
{
var thisAssembly = typeof(SwaggerConfig).Assembly;
c.SupportHeaderParams = true;
c.DocExpansion = DocExpansion.List;
c.SupportedSubmitMethods = new[] { HttpMethod.Get, HttpMethod.Post, HttpMethod.Put, HttpMethod.Head };
//c.InjectJavaScript(typeof(SwaggerConfig).Assembly, "WebApplication4.SwaggerExtensions.onComplete.js");
//c.EnableDiscoveryUrlSelector();
//c.InjectJavaScript(thisAssembly, "Swashbuckle.Dummy.SwaggerExtensions.testScript1.js");
//c.InjectStylesheet(thisAssembly, "Swashbuckle.Dummy.SwaggerExtensions.testStyles1.css");
c.EnableOAuth2Support("client_id", "realm", "Swagger UI");
});
// NOTE: If you want to customize the generated swagger or UI, use SwaggerSpecConfig and/or SwaggerUiConfig here ...
}
private static string GetXmlCommentsPath()
{
return String.Format(@"{0}\XmlComments.xml", AppDomain.CurrentDomain.BaseDirectory);
}
Now we've told Swagger we want to use OAuth, and this is how we want to use it. Done, right? Nope.
You need to add this folder, and files to your solution: https://github.com/domaindrivendev/Swashbuckle/tree/master/Swashbuckle.Dummy.Core/SwaggerExtensions
(you only need the .cs files)
Make sure your namespaces are right...
Then, you need to decorate your class in WebAPI, like this:
[ScopeAuthorize("test1")]
Now when you run it and get to the swagger page, you will see each operation that has that declaration will have the OAuth switch in the top right corner. When you click it, you can use Implicit grant flow and obtain a token that will be added to your reqeust.
This will only work with implicit grant from what I've found. It does seem they've tried to get AuthorizationCode Grant going, but the js files they have built only support implicit from what I can see.
Hope this helps someone. This is a powerful tool and I hope we see more sites use something like this.
Thanks and good luck!
I think most of what you had originally was ok. I'm using Swashbuckle 5.2.1 and got things working pretty well. I've just written a blog post (http://knowyourtoolset.com/2015/08/secure-web-apis-with-swagger-swashbuckle-and-oauth2-part-2/) that explains this in some detail, but the gist is adding the OperationFilter class(es) that define which of your API methods will get the OAuth21 toggle button on them. There are (sample) definitions of those in the SwaggerExtensions folder from GitHub as noted above, but really all you need as at least one class that implements IOperationFilter and its Apply method. I've got a sample class below. The class name really doesn't matter (nor where it is), you just need to include it (and any others if you have more) in the SwaggerConfig where the OperationFilter(s) are specified.
public class AssignOAuth2SecurityRequirements : IOperationFilter
{
public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
{
var actFilters = apiDescription.ActionDescriptor.GetFilterPipeline();
var allowsAnonymous = actFilters.Select(f => f.Instance).OfType<OverrideAuthorizationAttribute>().Any();
if (allowsAnonymous)
return; // must be an anonymous method
//var scopes = apiDescription.ActionDescriptor.GetFilterPipeline()
// .Select(filterInfo => filterInfo.Instance)
// .OfType<AllowAnonymousAttribute>()
// .SelectMany(attr => attr.Roles.Split(','))
// .Distinct();
if (operation.security == null)
operation.security = new List<IDictionary<string, IEnumerable<string>>>();
var oAuthRequirements = new Dictionary<string, IEnumerable<string>>
{
{"oauth2", new List<string> {"sampleapi"}}
};
operation.security.Add(oAuthRequirements);
}
}