i use springfox 2.9.2
I have api like:
#Api(tags = "Users")
#RestController
#RequestMapping("users")
public class UsersController {
#ApiOperation(value = "Creates a user")
#ApiResponses(value = {
#ApiResponse(code = 201, message = "user created"),
#ApiResponse(code = 401, message = "not authorized")})
#PostMapping(value = "/add")
public ResponseEntity addUser(#Valid #RequestBody UserDTO userDTO) {
...
}
to make this call user needs authorization token
Authorization: Bearer {token}
witch comes from authentication server.
i try to make first call to this server in swagger and pass it to controller requests like the one above.
So i do
#Bean
public Docket api() {
final String swaggerToken = "";
return new Docket(DocumentationType.SWAGGER_2)
#Bean
public .select()
.apis(RequestHandlerSelectors.basePackage("com.mbv.coros.notification.controller"))
.paths(PathSelectors.any())
.build()
.apiInfo(apiEndPointsInfo())
.securitySchemes(Arrays.asList(securityScheme()))
.securityContexts(Arrays.asList(securityContext()))
.useDefaultResponseMessages(false);
}
private SecurityScheme securityScheme() {
GrantType grantType = new ResourceOwnerPasswordCredentialsGrant(AUTH_SERVER + "/token");
SecurityScheme oauth = new OAuthBuilder().name("spring_oauth")
.grantTypes(Arrays.asList(grantType))
.scopes(Arrays.asList(scopes()))
.build();
return oauth;
private SecurityContext securityContext() {
return SecurityContext.builder()
.securityReferences(defaultAuth())
.build();
}
List<SecurityReference> defaultAuth() {
AuthorizationScope authorizationScope
= new AuthorizationScope("global", "accessEverything");
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
authorizationScopes[0] = authorizationScope;
return Lists.newArrayList(
new SecurityReference("JWT", authorizationScopes));
}
on Swagger ui authorization call returns the token successfully but it doesnt add it to request headers. It generates
curl -X GET "http://localhost:8080/users/get" -H "accept: */*"
if i set token like:
.securitySchemes(Arrays.asList(apiKey()))
private ApiKey apiKey() {
return new ApiKey("JWT", AUTHORIZATION_HEADER, "header");
}
it works perfectly.
any ideas why is this happening?
As far as I know, Swagger uses token only if you configure it to do so, and the configuration is done using the "Authorize" button on the top right of the Swagger UI page.
So, the ideal case would be:
Trigger Auth call which returns the token
Copy the token; Click on "Authorize" button and paste the JWT token in "Bearer "
After this, all the subsequent calls are supposed to use this token until you press logout.
Related
I have a ASP.NET MVC application with framework 4.7.2. The application is configured to use IdentityServer3 using OpenIDConnect. When user clicks on Logout button the following code is invoked
Action Method The logout action method get invoked first.
[HttpPost]
public ActionResult Logout()
{
Session.Clear();
if (Request.IsAuthenticated)
{
Request.GetOwinContext().Authentication.SignOut();
}
return Redirect("/");
}
In Owin Startup.cs i have configured OpenIDConnect. The RedirectToIdentityProvider event fires next.
Here, I am setting IdTokenHint when RequestType is Logout.
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
var cookieOptions = new CookieAuthenticationOptions
{
AuthenticationType = "Cookies",
LoginPath = new Microsoft.Owin.PathString("/Home"),
SlidingExpiration = true,
ExpireTimeSpan = GetCookieExpiration()
};
var openIdOptions = new OpenIdConnectAuthenticationOptions
{
Authority = ConfigurationManager.AppSettings["id:Authority"],
Scope = "openid email profile",
ClientId = "My ClientId",
RedirectUri = "http://localhost:58641/Home",
ResponseType = "id_token",
SignInAsAuthenticationType = "Cookies",
UseTokenLifetime = false,
Notifications = new OpenIdConnectAuthenticationNotifications
{
SecurityTokenValidated = (context) =>
{
//code here removed for brevity
return Task.FromResult(0);
},
RedirectToIdentityProvider = (context) =>
{
if (context.ProtocolMessage.RequestType == Microsoft.IdentityModel.Protocols.OpenIdConnectRequestType.LogoutRequest)
{
var idTokenHint = context.OwinContext.Authentication.User.FindFirst("id_token").Value;
context.ProtocolMessage.IdTokenHint = idTokenHint;
}
return Task.FromResult(0);
}
}
};
app.UseCookieAuthentication(cookieOptions);
app.UseOpenIdConnectAuthentication(openIdOptions);
MvcHandler.DisableMvcResponseHeader = true;
}
I fiddler i see it makes a call to
/identity/connect/endsession?id_token_hint= xxxxxxxx However, the HTTP Verb its using
is OPTIONS. So the IdentityServer throws error The requested resource does not support http method 'OPTIONS'
Not sure what i am missing Here.
Edit 1
In browser console i see the following error
Access to XMLHttpRequest at
'https://localhost:44300/identity/connect/endsession?id_token_hint=xxxxxxx'
(redirected from 'http://localhost:58641/account/logout') from origin
'http://localhost:58641' has been blocked by CORS policy: Response to
preflight request doesn't pass access control check: No
'Access-Control-Allow-Origin' header is present on the requested
resource.
Edit 2
I have another ASP.NET Application that has the same logout code. But its making GET request to endsession.
When you see the use of OPTIONS and the request contains the origin header, then that is a CORS preflight request. This is an extra security request that occurs when a JavaScript client tries to make an AJAX request to an API.
Is this intended to trigger the endsession from JavaScript? if so, you need for that client in identityServer set:
AllowedCorsOrigins =
{
"https://localhost:xxxxx"
},
This is set per client in IdentityServer.
how to create a token in postman and then after authorize person access that actionresult index method in asp.net mvc
now when I click on the send button of postman then direct access the index method that is issue I want to generate a token and then after authorize person access that method
staticvariable.cs
public static class staticvariable
{
public static HttpClient webapiclient = new HttpClient();
static staticvariable()
{
webapiclient.BaseAddress = new Uri("http://localhost:5718/api/");
webapiclient.DefaultRequestHeaders.Clear();
webapiclient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
}
}
studController.cs
public class studController : Controller
{
// GET: Home
public JsonResult Index()
{
IEnumerable<student> studlist;
HttpResponseMessage response = staticvariable.webapiclient.GetAsync("stud").Result;
studlist = response.Content.ReadAsAsync<IEnumerable<student>>().Result;
return Json(studlist,JsonRequestBehavior.AllowGet);
}
}
when click the send button of the postman and then access the index method that is issue
what i want to
when click on the send button of the postman then after generate the token means authoriz person can access that method
In Postman send an Http Post Request
Url : http://localhost:5718/token
in form-data send 3 Key -> values
grant_type:password // the word "password"
username:YOUR_USERNAME
password:YOUR_PASSWORD
then send the request
you will get a response with your Token
I'm able to login to Thingsboard website using my credentials, however when I try to connect the same using CURL command I get "Authentication Failed" error.
curl -X POST "https://cloud.thingsboard.io/api/auth/login" -d "{"username":"XYZPQR#ABCDLMN.com", "password":"Q#34&pwn"}" --header "Content-Type: application/json" --header "Accept: application/json"
Error Code
{"status":401,"message":"Authentication failed","errorCode":10,"timestamp":1542893993515}
However when I use the same user id and Password in my ASP.NET Application to fetch the authorization token, I do get the JWT token, but using the same token I'm unable to make any REST API call from Thingsboard.
ASP.NET CORE CODE
var response = new HttpResponseMessage();
var client = new HttpClient();
UserModel model = new UserModel { username = "XYZPQR#ABCDLMN.com", password = "Q#34&pwn" };
var content = new StringContent(JsonConvert.SerializeObject(model), Encoding.UTF8, "application/json");
response = await client.PostAsync("https://cloud.thingsboard.io/api/auth/login", content);
string data = await response.Content.ReadAsStringAsync();
var userToken = JsonConvert.DeserializeObject<UserToken>(data);
MediaTypeWithQualityHeaderValue contentType = new MediaTypeWithQualityHeaderValue("application/json");
client.DefaultRequestHeaders.Accept.Add(contentType);
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", userToken.token);
Uri url = new Uri("https://cloud.thingsboard.io/api/plugins/telemetry/DEVICE/431be6e0-e8ca-11e8-9e5c-3d544ba4fdfc/values/timeseries?keys=Electricity");
response = await client.GetAsync(url);
Model Class
public class UserModel {
public string username { get; set; }
public string password { get; set; }
}
public class UserToken
{
public string token { get; set; }
public string refreshToken { get; set; }
}
Please suggest, how to get the telemetry values from Thingsboard REST API.
It was a small mistake I was doing; I changed old code to new code(as shown below), and everything started working as expected.
Old code
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", userToken.token);
New Code
client.DefaultRequestHeaders.Add("X-Authorization", "Bearer " + userToken.token);
Thanks for support.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I have created one Asp core web api which will be consumed by C# console application outside the organization. This console application is scheduled to run periodically . So hits on Web api will come when console application run.
Please assist How Can i secure my Web Api to malware hit or unauthentic access. I can't use AD authentication as I am unable to register client application in AAD(Azure active directory) Please assist.
Generally speaking , there're lots ways to do that . For example , use a basic scheme authentication in which the client sends username:password with the base64-encoding . However . It's not that safe .
I suggest you use JWT token . The authentication of Jwt scheme is dead simple :
The client send a request to ask for a JWT token with client_id and client_key . (You might configure them in configuration file or database on server)
Tf the client_id and client_key matches , the Server send a response with a JWT access token , maybe an additional refresh token if you like ; otherwise , send a response with a 401.
The client consumes webapi with a Authorization: Bearer ${access_token} header. The server will decrypt the access_token and hit the correct action if valid.
Here's a how-to in details:
Dummy class to hold information
To represent the client_id and client_key sent by your console , Let's create a dummy Dto class :
public class AskForTokenRequest
{
public string ClientId { get; set; }
public string ClientKey { get; set; }
}
When creating and validating Jwt token , we need information about issuer , audience , and secret keys . To hold these information , let's create another dummy class :
public class SecurityInfo {
public static readonly string Issuer = "xxx";
public static readonly string[] Audiences = new[] { "yyy" };
public static readonly string SecretKey = "!##$%^&*()&!!!##$%^&*()&!!!##$%^&*()&!!!##$%^&*()&!!!##$%^&*()&!";
}
Before we move on , let's create a JwtTokenHelper to generate token :
The JwtTokenHelper helps to validate client_id & client_key and generate Jwt Token .
public class JwtTokenHelper
{
//private AppDbContext _dbContext { get; set; }
//public JwtTokenHelper(AppDbContext dbContext) {
// this._dbContext = dbContext;
//}
public virtual bool ValidateClient(string clientId, string clientKey)
{
// check the client_id & clientKey with database , config file , or sth else
if (clientId == "your_console_client_id" && clientKey == "your_console_client_key")
return true;
return false;
}
/// construct a token
public virtual JwtSecurityToken GenerateToken(string clientId, DateTime expiry, string audience)
{
ClaimsIdentity identity = new ClaimsIdentity(new GenericIdentity(clientId, "jwt"));
var token=new JwtSecurityToken
(
claims: identity.Claims,
issuer: SecurityInfo.Issuer,
audience: audience,
expires: expiry,
notBefore: DateTime.UtcNow,
signingCredentials: new SigningCredentials(
new SymmetricSecurityKey(Encoding.UTF8.GetBytes(SecurityInfo.SecretKey)),
SecurityAlgorithms.HmacSha256
)
);
return token;
}
public virtual string GenerateTokenString(string clientId, DateTime expiry,string audience)
{
// construct a jwt token
var token = GenerateToken(clientId,expiry,audience);
// convert the token to string
JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();
return tokenHandler.WriteToken(token);
}
}
Configure the server to enable JwtBearer authentication :
Add JwtTokenHelper to DI Container and Add authentication scheme of JwtBearer
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<JwtTokenHelper>();
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.RequireHttpsMetadata = false;
options.SaveToken = true;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidIssuer = SecurityInfo.Issuer,
ValidAudiences = SecurityInfo.Audiences,
ValidateAudience = true,
ValidateIssuer = true,
ValidateIssuerSigningKey = true,
IssuerSigningKeys = new List<SecurityKey> {
new SymmetricSecurityKey(Encoding.UTF8.GetBytes(SecurityInfo.SecretKey) )
},
ValidateLifetime = true,
ClockSkew = TimeSpan.FromMinutes(60)
};
});
services.AddMvc();
}
Don't forget to add app.UseAuthentication(); in your Configure() method .
How to use:
Now , Create a controller to generate Jwt token
[Route("/api/token")]
public class TokenController : Controller
{
private readonly JwtTokenHelper _tokenHelper;
public TokenController(JwtTokenHelper tokenHelper) {
this._tokenHelper = tokenHelper;
}
[HttpPost]
public IActionResult Create([FromBody] AskForTokenRequest client)
{
if(! this._tokenHelper.ValidateClient(client.ClientId , client.ClientKey))
return new StatusCodeResult(401);
DateTime expiry = DateTime.UtcNow.AddMinutes(60); // expires in 1 hour
var audience = "yyy";
var access_token = this._tokenHelper.GenerateTokenString(client.ClientKey, expiry,audience);
return new JsonResult(new {
access_token = access_token,
});
}
}
and protect you webapi with [Authorize] attribute :
public class HomeController : Controller
{
[Authorize]
public IActionResult GetYourWebApiMethod(){
return new ObjectResult(new {
Username = User.Identity.Name
});
}
}
I am using Restsharp within an MVC app, trying to call a backend MVC WebAPI protected by Thinktecture IdentityModel AuthenticationConfiguration.
MVC API Setup
My MVC API test is setup with the below:
private static void ConfigureAuth(HttpConfiguration config)
{
var authConfig = new AuthenticationConfiguration
{
DefaultAuthenticationScheme = "Basic",
EnableSessionToken = true,
SendWwwAuthenticateResponseHeader = true,
RequireSsl = false,
ClaimsAuthenticationManager = new AddCustomClaims(),
SessionToken = new SessionTokenConfiguration
{
EndpointAddress = "/token",
SigningKey = Convert.ToBase64String(CryptoRandom.CreateRandomKey(32)),
DefaultTokenLifetime = new TimeSpan(1, 0, 0)
}
};
authConfig.AddBasicAuthentication((username, password) =>
{
return username == "admin" && password == "password";
});
config.MessageHandlers.Add(new AuthenticationHandler(authConfig));
}
private static void ConfigureCors(HttpConfiguration config)
{
var corsConfig = new WebApiCorsConfiguration();
config.MessageHandlers.Add(new CorsMessageHandler(corsConfig, config));
corsConfig
.ForAllOrigins()
.AllowAllMethods()
.AllowAllRequestHeaders();
}
Javascript works OK
I know 100% the token I am sending with Restsharp is correct and working with equivalent json calls (the token used in the javascript is the same used in the Web MVC controller as its stored in the Session array):
var authToken = config.authToken,
baseUri = config.baseUri,
configureRequest = function (xhr) {
xhr.setRequestHeader("Authorization", "Session " + authToken);
},
errorHandler = function (xhr, status, error) {
if (xhr.status === 401 && config.onAuthFail) {
config.onAuthFail(xhr, status, error);
}
};
Calling the API from my MVC web front end client app - Authorization has been denied for this request
Then in my MVC app controller action i use RestSharp as follows:
public ActionResult Test()
{
var token = Session[Constants.SessionTokenKey] as string;
var client = new RestClient(new Uri("http://localhost:65104/"));
var request = new RestRequest("contacts", Method.GET);
string authHeader = System.Net.HttpRequestHeader.Authorization.ToString();
request.AddHeader(authHeader, string.Format("Authorization Session {0}", token));
var json = client.Execute(request);
// break point here checking the status it has been denied
return View("Index");
}
Checking the status, it returns "{\"message\":\"Authorization has been denied for this request.\"}".
I have tried adding the token with Restsharp request methods with request.AddHeader(authHeader, string.Format("Authorization Session {0}", token)); and also with request.AddHeader(authHeader, string.Format("JWT {0}", token));, but get the same access denied for both ways.
What am I doing wrong please or any recommendations on where to look?
Looks like your JavaScript code and RestSharp request code doesn't match.
In JS you set a header with name Authorization and give it a value Session sometoken:
xhr.setRequestHeader("Authorization", "Session " + authToken);
In RestSharp you assign a header with name Authorization a value Authorization Session sometoken
request.AddHeader(authHeader, string.Format("Authorization Session {0}", token));
So I would suggest changing your RestSharp AddHeader code to this:
request.AddHeader(authHeader, string.Format("Session {0}", token));