Using swagger-codegen with username and password basic auth
Asked Answered
S

3

7

I have a django rest_framework API, Swagger and a Swagger UI. When I am not logged in I can see a very limited view of "login" and "docs". When I am logged in I can see lots of stuff.

I am trying to use the swagger-codegen to generate a client:

java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar \
generate -i http://127.0.0.1:8080/api/docs/ -l python -o myclient

However, it only generates a very limited client that provides the "login" and "docs" functionality.

How do I let swagger-codegen know how to login using http basic authentication, in order for it to generate a more complete client?

The docs says I should do the following, but I do not know what it expects:

    -a <authorization>, --auth <authorization>
        adds authorization headers when fetching the swagger definitions
        remotely. Pass in a URL-encoded string of name:header with a comma
        separating multiple values
Signorina answered 8/2, 2017 at 17:18 Comment(0)
A
16

Since you are using http basic authentication the command should be:

java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar \
generate -i http://127.0.0.1:8080/api/docs/ -l python -o myclient -a "Authorization:Basic QWxhZGRpbjpPcGVuU2VzYW1l"

Where QWxhZGRpbjpPcGVuU2VzYW1l is your username:password encoded in base64.

Here you can have a look at the code that will parse this option.

Apatetic answered 9/2, 2017 at 12:55 Comment(3)
You can use this site to encode the credentials using the following format: username:password.Rotative
I found this solution close but not quite correct. As the documentation (confusingly) states and the source link shows, in addition to parsing a string for an auth header key:value pair via a literal : delimiter, it is also expecting the key and value to be UTF-8 URLEncoded. e.g. to pass an Authorization header with base64 creds of admin:admin (Basic YWRtaW46YWRtaW4=) the final arg should be -a Authorization:Basic%20YWRtaW46YWRtaW4%3DMilkfish
Surely there must be some way to provide credentials without hard-coding them into the source code generation process. Aside from being insecure, does that mean we need to regenerate and recompile our code if a password changes?Spenser
L
0

To provide credentials to all requests:

var creds = new NetworkCredential("username", "password");
var encoded = Convert.ToBase64String(Encoding.GetEncoding("ISO-8859-1").GetBytes(creds.UserName + ":" + creds.Password));
            
Configuration.Default.AddDefaultHeader("Authorization", "Basic " + encoded);

//use the API
var searchAPI = new SearchAPI();
var files = searchAPI.GetFiles();

To provide the credentials to just one API call:

var creds = new NetworkCredential("username", "password");
var encoded = Convert.ToBase64String(Encoding.GetEncoding("ISO-8859-1").GetBytes(creds.UserName + ":" + creds.Password));

var searchAPI = new SearchAPI();
searchAPI.Configuration.AddDefaultHeader("Authorization", "Basic " + encoded);

//use the API
var files = searchAPI.GetFiles();
Ludovico answered 20/4, 2021 at 10:14 Comment(0)
L
0

An alternative is to use a custom authenticator.

var basicAuthenticator = new BasicAuthenticator(Configuration.Default.ApiClient.RestClient.BaseUrl.ToString(), "username", "password");
Configuration.Default.ApiClient.RestClient.Authenticator = basicAuthenticator;

Which uses the BasicAuthenticator class:

public class BasicAuthenticator : IAuthenticator
{
    private readonly string _baseUrl;
    private readonly string _userName;
    private readonly string _password;
    private readonly CredentialCache _credentialCache;

    public BasicAuthenticator(string baseUrl, string userName, string password)
    {
        _baseUrl = baseUrl;
        _userName = userName;
        _password = password;

        _credentialCache = new CredentialCache
        {
            {new Uri(_baseUrl), "Basic", new NetworkCredential(_userName, _password)}
        };
    }

    public void Authenticate(IRestClient client, IRestRequest request)
    {
        request.Credentials = _credentialCache;

        if (request.Parameters.Any(parameter =>
                        parameter.Name.Equals("Authorization", StringComparison.OrdinalIgnoreCase)))
        {
            return;
        }
        request.AddParameter("Authorization", GetBasicAuthHeaderValue(), ParameterType.HttpHeader);
    }


    private string GetBasicAuthHeaderValue()
    {
        return string.Format("Basic {0}",
                        Convert.ToBase64String(Encoding.ASCII.GetBytes(string.Format("{0}:{1}",
                            _userName, _password))));
    }
}

There's a known issue with RestSharp that it won't provide the Basic Auth details to second request (after a redirect). Using the above authenticator resolves that.

Ludovico answered 21/4, 2021 at 2:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.