13

I'm trying to use Swashbuckle 5.0.x with OAuth2. I want to use OAuth2's Resource Owner Password Credentials Grant. I basically only want to ask for a token first and include this token in each request (e.g. no need for scopes).

Can anyone help with this? How do I have to configure swagger/swashbuckle?

Dunken
  • 8,481
  • 7
  • 54
  • 87

4 Answers4

15

Thank you @Dunken. Your answer almost solve my problem, but to make it work with latest Swashbuckle version I had to change it a bit like this

$('#explore').off();

$('#explore').click(function () {
   var key = $('#input_apiKey')[0].value;
   var credentials = key.split(':'); //username:password expected

$.ajax({
    url: "yourAuthEndpoint",
    type: "post",
    contenttype: 'x-www-form-urlencoded',
    data: "grant_type=password&username=" + credentials[0] + "&password=" + credentials[1],
    success: function (response) {
        var bearerToken = 'Bearer ' + response.access_token;

        window.swaggerUi.api.clientAuthorizations.add('Authorization', new SwaggerClient.ApiKeyAuthorization('Authorization', bearerToken, 'header'));
        window.swaggerUi.api.clientAuthorizations.remove("api_key");
        alert("Login successfull");
       },
       error: function (xhr, ajaxoptions, thrownerror) {
        alert("Login failed!");
       }
    });
});
prime_z
  • 544
  • 6
  • 9
  • Perfect! Please, include the last `});` into the code block. – Neshta Sep 14 '15 at 14:25
  • Trying to do this. I have added the script to my project in the root. Marked it as an embedded resource but when I rebuild and load the swagger UI it says it cannot fine it. – ToddB Feb 02 '16 at 15:29
  • I should add, I set up the following file name SwaggerJWTScript.js. My script is: c.InjectJavaScript(thisAssembly, ".SwaggerExtensions.SwaggerJWTScript.js"); – ToddB Feb 02 '16 at 15:39
  • Sorry for late answer. Check that js file is not only embedded resource, but is also marked as `Copy Always`. Use following code configuration `c => c.InjectJavaScript(typeof().Assembly, ".onComplete.js"))` – prime_z Feb 16 '16 at 16:10
  • @prime_z This is the full, correct answer to the question. Thanks heaps! – robnick Jun 03 '16 at 03:41
11

OK, I solved it like this:

Add a JavaScript completion-handler to swagger:

config
    .EnableSwagger(c => {
                    //do stuff
    })
    .EnableSwaggerUi(c => {
        c.InjectJavaScript(typeof(Startup).Assembly, "MyNamespace.SwaggerExtensions.onComplete.js");
    });

Take username:password from the API_KEY textbox:

$('#input_apiKey').change(function () {
    var key = $('#input_apiKey')[0].value;
    var credentials = key.split(':'); //username:password expected
    $.ajax({
        url: "myURL",
        type: "post",
        contenttype: 'x-www-form-urlencoded',
        data: "grant_type=password&username=" + credentials[0] + "&password=" + credentials[1],
        success: function (response) {
            var bearerToken = 'Bearer ' + response.access_token;
            window.authorizations.add('key', new ApiKeyAuthorization('Authorization', bearerToken, 'header'));
        },
        error: function (xhr, ajaxoptions, thrownerror) {
            alert("Login failed!");
        }
    });
});
Dunken
  • 8,481
  • 7
  • 54
  • 87
  • Could you please specify where you added first code snippet "config.EnableSwagger ..."? Second one as I got you added to index.html, am i right? – zubactik May 19 '15 at 14:08
  • I added this in my Startup.cs (OWIN startup). The second one is a JavaScript file (onComplete.js), an embedded resource I added to my ASP.NET Web API project. – Dunken May 19 '15 at 14:34
  • 1
    I had to post a new answer in order to make it work with latest version – prime_z Jul 30 '15 at 14:31
  • This doesnt work for me, I get the token back, but when the request hits my api, the Authorization header is null, can you post your SwaggerConfig please? – Derek Jan 21 '16 at 17:12
  • @Derek: I don't use a SwaggerConfig and I don't use any button. Please share your code in a new post and let me know. – Dunken Jan 26 '16 at 16:38
  • http://stackoverflow.com/questions/34929280/swashbuckle-swagger-oauth-resource-owner-password-flow here is the question ive asked. I'm using swagger via swashbuckle for ASP.NET Web APi. @Dunken - Your help is very much appreciated. – Derek Jan 26 '16 at 17:15
1

Similar answers to @rui-estreito and @prime-z, but this prompts for a username and password when 'exploring' the API for the first time.

1 swagger.config

c.InjectJavaScript(thisAssembly, "<project namespace>.CustomContent.apikey.js")

2 create \\CustomContent\apikey.js

    (function () {
    $(function () {
        console.log("loaded custom auth");
        $('#input_apiKey').off();
        $('#explore').off();
        $('#explore').click(function () {
            var credentials_un = prompt("Username");
            var credentials_password = prompt("Password");
            var client_id = $('#input_apiKey')[0].value;

            $.ajax({
                url: document.location.origin + "/token",
                type: "post",
                contenttype: 'x-www-form-urlencoded',
                data: "grant_type=password&username=" + credentials_un + "&password=" + credentials_password + "&client_id=" + client_id,
                success: function (response) {
                    var bearerToken = 'Bearer ' + response.access_token;
                    window.swaggerUi.api.clientAuthorizations.add('Authorization', new SwaggerClient.ApiKeyAuthorization('Authorization', bearerToken, 'header'));
                    alert("Login successfull");
                },
                error: function (xhr, ajaxoptions, thrownerror) {
                    alert("Login failed!");
                }
            });
        });
        /*
        */
    });
})();

3 modify apikey.js file properties

BuildAction change to 'Embedded Resource'

OzBob
  • 4,227
  • 1
  • 39
  • 48
0

i had a problem where the solution .InjectJavaScript() resolved my problem, the diference is that i have a custom grant type, since the base code of swagger-ui-min.js have the grant password hardcoded for the flow password, the solution was override their code:

$(function () {


window.SwaggerUi.Views.AuthView = Backbone.View.extend({
    events: (...),
    tpls: (...),
    selectors: {
        innerEl: ".auth_inner",
        authBtn: ".auth_submit__button"
    },
    initialize: function (e)(...),
    render: function ()(...),
    authorizeClick: function (e)(...),
    authorize: function ()(...),
    logoutClick: function (e)(...),
    handleOauth2Login: function (e)(...),
    clientCredentialsFlow: function (e, t, n)(...),
    passwordFlow: function (e, t, n) {
        this.accessTokenRequest(e, t, n, "mygrant", {
            username: t.username,
            password: t.password
        })
    },
    accessTokenRequest: function (e, t, n, r, i) {
        i = $.extend({}, {
            scope: e.join(" "),
            grant_type: r
        }, i);
        var a = {};
        switch (t.clientAuthenticationType) {
            case "basic":
                a.Authorization = "Basic " + btoa(t.clientId + ":" + t.clientSecret);
                break;
            case "request-body":
                i.client_id = t.clientId,
                    i.client_secret = t.clientSecret
        }
        $.ajax(...)
    }
});
});

The (...) have the original code that i copy from the swagger-ui-min.js.

Rui Estreito
  • 262
  • 1
  • 10