Skip to content

Instantly share code, notes, and snippets.

@hubert17
Forked from mbasaran/CustomSwagger.js
Last active April 20, 2021 19:49
Show Gist options
  • Save hubert17/44c3f772a414f9268e1a1da8c92a13d7 to your computer and use it in GitHub Desktop.
Save hubert17/44c3f772a414f9268e1a1da8c92a13d7 to your computer and use it in GitHub Desktop.
Add bearer token automatically to Swagger UI using Swashbuckle Asp.Net Core
(function () {
function getJwt(user, pass, success, error, complete) {
//console.log('getJwt ', user);
$.ajax({
url: '/TOKEN',
type: 'POST',
contentType: "application/json",
dataType: "json",
data: JSON.stringify({
username: user,
password: pass
}),
success: function (data) {
success && success(data.data.token);
},
error: function (jqXhr, err, msg) {
error && error(JSON.parse(jqXhr.responseText).error_description);
},
complete: complete
});
}
function setNativeValue(element, value) {
const valueSetter = Object.getOwnPropertyDescriptor(element, 'value').set;
const prototype = Object.getPrototypeOf(element);
const prototypeValueSetter = Object.getOwnPropertyDescriptor(prototype, 'value').set;
if (valueSetter && valueSetter !== prototypeValueSetter) {
prototypeValueSetter.call(element, value);
} else {
valueSetter.call(element, value);
}
}
function setJwt(key) {
//console.log("setJwt ", key);
var inputAuth = $('.auth-container :input[type=text]')[1];
//inputAuth.off().val("Bearer " + key).change();
//inputAuth.attr('value', 'Bearer ' + key);
try {
setNativeValue(inputAuth, 'Bearer ' + key);
inputAuth.dispatchEvent(new Event('input', { bubbles: true }));
}
catch (err) {
//console.log(err.message);
}
}
$(function () {
setTimeout(() => {
//$('.btn.authorize').click(function () {
$(document).on("click", '.btn.authorize', function () {
var autBtnWrapper = $('.auth-btn-wrapper');
if (autBtnWrapper.length > 1) {
$('.auth-btn-wrapper').first().remove();
}
var inputAuth = $('.auth-container :input[type=text]').eq(1);
inputAuth.val('Bearer ');
var inputEvent = $(':input[name=username],:input[name=password]');
inputEvent.off().on('change', function () {
var user = $(':input[name=username]').val();
var pass = $(':input[name=password]').val();
if (user && pass) {
inputAuth.prop("disabled", true);
inputAuth.val("Please wait as we get your token...");
getJwt(user, pass,
function (jwt) {
if (jwt !== undefined) {
inputAuth.css('background', '#65f30f');
setJwt(jwt);
window.localStorage.setItem('key', jwt);
} else {
console.log('Check the json response for typo and casing...');
}
},
function (err) {
inputAuth.css('background', '#fd7474');
alert('Invalid login. ', err);
inputAuth.val('');
inputEvent.eq(1).val('');
inputEvent.eq(1).focus();
}, function () {
inputAuth.prop("disabled", false);
});
}
});
setTimeout(() => {
var oldKey = window.localStorage.getItem('key');
if (oldKey) {
setJwt(oldKey);
}
}, 2000);
});
}, 1);
});
})();
public void ConfigureServices(IServiceCollection services)
{
// init codes
//..
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new Info { Title = "BermudaPay API", Version = "v1" });
c.AddSecurityDefinition("BasicAuth", new BasicAuthScheme { Description = "Login" });
c.AddSecurityDefinition("Bearer", new ApiKeyScheme
{
Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"",
Name = "Authorization",
In = "header",
Type = "apiKey"
});
var security = new Dictionary<string, IEnumerable<string>>
{
{"Bearer", new string[] { }},
};
c.AddSecurityRequirement(security);
});
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseStaticFiles();
app.UseAuthentication();
app.UseCorsMiddleware();
// Enable middleware to serve generated Swagger as a JSON endpoint.
app.UseSwagger();
// Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
// specifying the Swagger JSON endpoint.
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "BermudaPay API V1");
//c.InjectJavascript("/static/js/CustomSwagger.js");
c.IndexStream = () => GetType().Assembly.GetManifestResourceStream("api.Resources.Swagger.index.html");
});
app.UseMvc();
}
<!-- HTML for static distribution bundle build -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>%(DocumentTitle)</title>
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,700|Source+Code+Pro:300,600|Titillium+Web:400,600,700" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="./swagger-ui.css" >
<link rel="icon" type="image/png" href="./favicon-32x32.png" sizes="32x32" />
<link rel="icon" type="image/png" href="./favicon-16x16.png" sizes="16x16" />
<style>
html
{
box-sizing: border-box;
overflow: -moz-scrollbars-vertical;
overflow-y: scroll;
}
*,
*:before,
*:after
{
box-sizing: inherit;
}
body {
margin:0;
background: #fafafa;
}
</style>
%(HeadContent)
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="position:absolute;width:0;height:0">
<defs>
<symbol viewBox="0 0 20 20" id="unlocked">
<path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V6h2v-.801C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8z"></path>
</symbol>
<symbol viewBox="0 0 20 20" id="locked">
<path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8zM12 8H8V5.199C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8z"/>
</symbol>
<symbol viewBox="0 0 20 20" id="close">
<path d="M14.348 14.849c-.469.469-1.229.469-1.697 0L10 11.819l-2.651 3.029c-.469.469-1.229.469-1.697 0-.469-.469-.469-1.229 0-1.697l2.758-3.15-2.759-3.152c-.469-.469-.469-1.228 0-1.697.469-.469 1.228-.469 1.697 0L10 8.183l2.651-3.031c.469-.469 1.228-.469 1.697 0 .469.469.469 1.229 0 1.697l-2.758 3.152 2.758 3.15c.469.469.469 1.229 0 1.698z"/>
</symbol>
<symbol viewBox="0 0 20 20" id="large-arrow">
<path d="M13.25 10L6.109 2.58c-.268-.27-.268-.707 0-.979.268-.27.701-.27.969 0l7.83 7.908c.268.271.268.709 0 .979l-7.83 7.908c-.268.271-.701.27-.969 0-.268-.269-.268-.707 0-.979L13.25 10z"/>
</symbol>
<symbol viewBox="0 0 20 20" id="large-arrow-down">
<path d="M17.418 6.109c.272-.268.709-.268.979 0s.271.701 0 .969l-7.908 7.83c-.27.268-.707.268-.979 0l-7.908-7.83c-.27-.268-.27-.701 0-.969.271-.268.709-.268.979 0L10 13.25l7.418-7.141z"/>
</symbol>
<symbol viewBox="0 0 24 24" id="jump-to">
<path d="M19 7v4H5.83l3.58-3.59L8 6l-6 6 6 6 1.41-1.41L5.83 13H21V7z"/>
</symbol>
<symbol viewBox="0 0 24 24" id="expand">
<path d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"/>
</symbol>
</defs>
</svg>
<div id="swagger-ui"></div>
<!-- Workaround for https://github.com/swagger-api/swagger-editor/issues/1371 -->
<script>
if (window.navigator.userAgent.indexOf("Edge") > -1) {
console.log("Removing native Edge fetch in favor of swagger-ui's polyfill")
window.fetch = undefined;
}
</script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="./swagger-ui-bundle.js"> </script>
<script src="./swagger-ui-standalone-preset.js"> </script>
<script>
window.onload = function () {
var configObject = JSON.parse('%(ConfigObject)');
var oauthConfigObject = JSON.parse('%(OAuthConfigObject)');
// Apply mandatory parameters
configObject.dom_id = "#swagger-ui";
configObject.presets = [SwaggerUIBundle.presets.apis, SwaggerUIStandalonePreset];
configObject.layout = "StandaloneLayout";
// If oauth2RedirectUrl isn't specified, use the built-in default
if (!configObject.hasOwnProperty("oauth2RedirectUrl"))
configObject.oauth2RedirectUrl = window.location.href.replace("index.html", "oauth2-redirect.html");
// Build a system
const ui = SwaggerUIBundle(configObject);
// Apply OAuth config
ui.initOAuth(oauthConfigObject);
}
</script>
<!-- Custom Scripts -->
<script src="/static/js/CustomSwagger.js"> </script>
</body>
</html>
@acds
Copy link

acds commented Jun 23, 2019

Hi @hubert17, This looks really promising!

How difficult is to to update this to use a OAuth2Scheme SecurityDefinition with "password" flow in lieu of the BasicAuthScheme you have here, with the addition of and additional and separate ApiKeyScheme such that the API support both bearer tokens (via the OAuth2Scheme such that once makes a request again a token url) and API Keys.

Any hints greatly appreciated!

EDIT:

I think I understand what you have done here better, how (ala the OAuth2Scheme) can I pass in a customer token URL for the getJwt function, as in my case it needs to be configurable for different contexts, and additionally I'd also need to support an additonal ApiKeyScheme for a seperate API Key - not a Bearer token.

  options.AddSecurityDefinition("APIKey", new ApiKeyScheme { 
        In = "header", 
        Description = "Please enter APIKey", 
        Name = "APIKey", Type = "apiKey" 
    });             

@katikareddylava
Copy link

Hi @hubert17 can you please explain belowe line
c.IndexStream = () => GetType().Assembly.GetManifestResourceStream("api.Resources.Swagger.index.html");

i am unable to run swagger when i add above line please tell me where to add swagger.index.html file in .net core project

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment