I am trying to generate my C# client for a web api using Oath. It generates for all my controllers except for /token :
OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/Token"),
...
}
I have no idea if this is even possible. Can anyone tell me? Anyway meanwhile I added this to my generated json by hand:
"/Token":{
"post":{
"tags":[
"Auth"
],
"consumes":[
"application/x-www-form-urlencoded"
],
"parameters":[
{
"name":"grant_type",
"in":"formData",
"required":true,
"type":"string"
},
{
"name":"username",
"in":"formData",
"required":false,
"type":"string"
},
{
"name":"password",
"in":"formData",
"required":false,
"type":"string"
}
],
"responses": {
"200": {
"description": "",
"schema": {
"type": "object",
"items": {
"$ref": "#/definitions/AuthViewModel"
}
},
"x-nullable": true
}
}
}
}
"AuthViewModel": {
"type": "object",
"additionalProperties": false,
"properties": {
"access_token": {
"type": "string"
},
"token_type": {
"type": "string"
},
"expires_in": {
"type": "string"
},
"userName": {
"type": "string"
},
".issued": {
"type": "string"
},
".expires": {
"type": "string"
}
}
},
I do not know yet if it would work, but if I could avoid doing it... I would prefer!
The OAuth endpoint is probably a OWIN/ASP.NET Core middleware. They cannot be analyzed, only controller classes are... You can manually append operations in the PostProcess method or with a IDocumentProcessor (C#) or with a Swagger spec template (cmd line, nswag.json)
Here's what I'm using. In app startup where you configure NSwag.
The API schema says it consumes _application/x-www-form-urlencoded_, but the NSwag CS client generator generates code to post a multi-part form (_multipart/form-data_), which is incompatible with the underlying API code. I have to fix up that part of the code whenever I regenerate the client.
app.UseSwaggerUi3(typeof(SwaggerConfig).Assembly, settings =>
{
settings.GeneratorSettings.DefaultPropertyNameHandling = PropertyNameHandling.CamelCase;
settings.PostProcess = document =>
{
. . .
AddTokenEndpointApiSchema(document);
};
});
private static void AddTokenEndpointApiSchema(SwaggerDocument document)
{
var tokenOpr = new SwaggerOperation()
{
OperationId = "Token_Post"
};
if (tokenOpr.Consumes == null) { tokenOpr.Consumes = new List<string>(); }
tokenOpr.Consumes.Add("application/x-www-form-urlencoded");
if (tokenOpr.Produces == null) { tokenOpr.Produces = new List<string>(); }
tokenOpr.Produces.Add("application/json");
if (tokenOpr.Tags == null) { tokenOpr.Tags = new List<string>(); }
tokenOpr.Tags.Add("Token");
tokenOpr.Parameters.Add(new SwaggerParameter
{
Name = "grant_type",
Description = "",
IsRequired = true,
Kind = SwaggerParameterKind.FormData,
Type = JsonObjectType.String
});
var tokenResp = new SwaggerResponse
{
Description = "Authentication token and meta data.",
Schema = new JsonSchema4()
};
tokenResp.Schema.Properties.Add("access_token", new JsonProperty { Type = JsonObjectType.String, IsRequired = true });
tokenResp.Schema.Properties.Add("token_type", new JsonProperty { Type = JsonObjectType.String, IsRequired = true });
tokenResp.Schema.Properties.Add("expires_in", new JsonProperty { Type = JsonObjectType.Integer, IsRequired = true, Format = JsonFormatStrings.Integer });
tokenResp.Schema.Properties.Add("userName", new JsonProperty { Type = JsonObjectType.String, IsRequired = true });
tokenResp.Schema.Properties.Add(".issued", new JsonProperty { Type = JsonObjectType.String, IsRequired = true, Format = JsonFormatStrings.DateTime });
tokenResp.Schema.Properties.Add(".expires", new JsonProperty { Type = JsonObjectType.String, IsRequired = true, Format = JsonFormatStrings.DateTime });
tokenOpr.Responses.Add("200", tokenResp);
var path = new SwaggerPathItem();
path.Add(SwaggerOperationMethod.Post, tokenOpr);
document.Paths.Add("token", path);
}
Thx for sharing