The Aqueduct docs say that the server should return a refresh token. It should look like this:
{
"access_token" : "Abca09zzzza2o2kelmzlli3ijlka",
"token_type" : "bearer",
"refresh_token" : "lkmLIAmooa898nm20jannnnnxaww",
"expire_in" : 3600
}
But this is what the server actually gives:
{
"access_token": "uArVqRgpGKv98aNJpziSmTQiFaX2Ebrz",
"token_type": "bearer",
"expires_in": 86399
}
There is no refresh_token.
Here is what my controller looks like:
class DemoChannel extends ApplicationChannel {
ManagedContext context;
AuthServer authServer;
#override
Future prepare() async {
logger.onRecord.listen((rec) => print("$rec ${rec.error ?? ""} ${rec.stackTrace ?? ""}"));
final config = WordConfig(options.configurationFilePath);
final dataModel = ManagedDataModel.fromCurrentMirrorSystem();
final persistentStore = PostgreSQLPersistentStore.fromConnectionInfo(
config.database.username,
config.database.password,
config.database.host,
config.database.port,
config.database.databaseName);
context = ManagedContext(dataModel, persistentStore);
final authStorage = ManagedAuthDelegate<User>(context);
authServer = AuthServer(authStorage);
}
#override
Controller get entryPoint {
final router = Router();
router
.route('/register')
.link(() => RegisterController(context, authServer));
router
.route('/auth/token')
.link(() => AuthController(authServer));
router
.route('/words/[:id]')
.link(() => Authorizer.bearer(authServer))
.link(() => WordsController(context));
return router;
}
}
My AuthController is just the standard one that comes with Aqueduct. I didn't even see any parameters to adjust in the source code.
How do I make the server send back a refresh token?
It sounds like you are authenticating a public OAuth 2 client. By rule, a public client cannot have a refresh token. You must use a confidential client. A client is confidential when it has a secret. Use the —secret option when creating your client.
Related
I'm working with an angular front end connected to a .NET Core back end and using OpenIddict for authorization. When I land on my login page, the url looks as follows:
https://localhost:44340/Account/Login?ReturnUrl=%2Fconnect%2Fauthorize%3Fresponse_type%3Dcode%26client_id%3DclientIDExample%26state%3DYUVBdDJvUG04SUpVTzZqSEJvRlMxWFZnWU0xSUVsSi1IVnR1WEY2R3pCMG1m%26redirect_uri%3Dhttp%253A%252F%252Flocalhost%253A4200%26scope%3Dopenid%2520profile%2520email%2520offline_access%26code_challenge%3DAg0TCRqJBaFqpa8sJb--J67Yd88tNPmouGonUvBbBbM%26code_challenge_method%3DS256%26nonce%3DYUVBdDJvUG04SUpVTzZqSEJvRlMxWFZnWU0xSUVsSi1IVnR1WEY2R3pCMG1m
Here is the 'user friendly' url I want the users to see, not the authorize endpoint:
https://localhost:44340/Account/Login
Here is the part of my Authorization code that I'm hitting:
[HttpGet("~/connect/authorize")]
[HttpPost("~/connect/authorize")]
[IgnoreAntiforgeryToken]
public async Task<IActionResult> Authorize()
{
var request = HttpContext.GetOpenIddictServerRequest() ??
throw new InvalidOperationException("The OpenID Connect request cannot be retrieved.");
// Retrieve the user principal stored in the authentication cookie.
// If it can't be extracted, redirect the user to the login page.
var result = await HttpContext.AuthenticateAsync(IdentityConstants.ApplicationScheme);
if (result is null || !result.Succeeded)
{
// If the client application requested promptless authentication,
// return an error indicating that the user is not logged in.
if (request.HasPrompt(Prompts.None))
{
return Forbid(
authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
properties: new AuthenticationProperties(new Dictionary<string, string>
{
[OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.LoginRequired,
[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = "The user is not logged in."
}));
}
return Challenge(
authenticationSchemes: IdentityConstants.ApplicationScheme,
properties: new AuthenticationProperties
{
RedirectUri = Request.PathBase + Request.Path + QueryString.Create(
Request.HasFormContentType ? Request.Form.ToList() : Request.Query.ToList())
});
}
}
Here is my Startup class:
public class Startup
{
public Startup(IConfiguration configuration, IHostEnvironment env)
{
Configuration = configuration;
_env = env;
}
public IConfiguration Configuration { get; }
public IHostEnvironment _env { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
var connectionString = Configuration[$"Connections:DefaultConnection"];
var EncryptionCertificate = new X509Certificate2(Convert.FromBase64String(Configuration["EncCert"]), (string)null, X509KeyStorageFlags.MachineKeySet);
var SignCertificate = new X509Certificate2(Convert.FromBase64String(Configuration["SigCert"]), (string)null, X509KeyStorageFlags.MachineKeySet);
services.AddRazorPages();
//DbContext OnConfiguring gets done here
services.AppDataContext(connectionString);
// OpenIddict offers native integration with Quartz.NET to perform scheduled tasks
// (like pruning orphaned authorizations/tokens from the database) at regular intervals.
services.AddQuartz(options =>
{
options.UseMicrosoftDependencyInjectionJobFactory();
options.UseSimpleTypeLoader();
options.UseInMemoryStore();
});
// Register the Quartz.NET service and configure it to block shutdown until jobs are complete.
services.AddQuartzHostedService(options => options.WaitForJobsToComplete = true);
services.AddIdentity<ApplicationUserModel, IdentityRole>()
.AddEntityFrameworkStores<DataContext>()
.AddDefaultTokenProviders();
services.Configure<IdentityOptions>(options =>
{
// Configure Identity to use the same JWT claims as OpenIddict instead
// of the legacy WS-Federation claims it uses by default (ClaimTypes),
// which saves you from doing the mapping in your authorization controller.
options.ClaimsIdentity.UserNameClaimType = Claims.Name;
options.ClaimsIdentity.UserIdClaimType = Claims.Subject;
options.ClaimsIdentity.RoleClaimType = Claims.Role;
// Note: to require account confirmation before login,
// register an email sender service (IEmailSender) and
// set options.SignIn.RequireConfirmedAccount to true.
//
// For more information, visit https://aka.ms/aspaccountconf.
options.SignIn.RequireConfirmedAccount = false;
});
services.IdentityServer(EncryptionCertificate, SignCertificate);
services.AddAuthentication(Configuration);
//Adds some claim data
services.AddScoped<IUserClaimsPrincipalFactory<ApplicationUserModel>, AdditionalUserClaimsPrincipalFactory>();
services.AddCors(options => options.AddPolicy("AllowCors",
builder =>
{
builder.SetIsOriginAllowed(_ => true)
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
})
);
if (_env.IsDevelopment())
{
//Script will populate Database but should be scripted for production
services.AddHostedService<Worker>();
}
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCors("AllowCors");
//Middleware that takes care of authorization and authentication
//Should always happen before the endpoints
//These methods allow for decorating Controllers with the Authorize attribute, which controls page and feature access
app.UseAuthentication();
app.UseAuthorization();
//Endpoints instead of Razor pages
//Because using APIs and Angular
app.UseEndpoints(endpoints =>
{
//endpoints.MapControllers();
endpoints.MapDefaultControllerRoute();
});
}
}
Do I need a rewrite? A redirect? I need to retain the endpoint but I can't be showing the users the entire endpoint.
I think most system will present you with that 'ugly' link, event if you try to login with Google or Facebook, you will be presented with the same long link.
There are ongoing work in the community that could result in nicer links and one is Pushed Authorization Requests (PAR), but I doubt all token providers supports it and I don't know what the support is for that in ASP.NET Core today.
I ended up having to store the long endpoint in a helper so i could pass the endpoint but get a nice looking ReturnUri, which I'm now passing as 'Home':
New link is:
https://localhost:44340/Account/Login?ReturnUrl=Home
[HttpGet("~/connect/authorize")]
[HttpPost("~/connect/authorize")]
[IgnoreAntiforgeryToken]
public async Task<IActionResult> Authorize()
{
var request = HttpContext.GetOpenIddictServerRequest() ??
throw new InvalidOperationException("The OpenID Connect request cannot be retrieved.");
if (_urlHelper != null)
{
_urlHelper.Value.urlEndpoint = Request.PathBase + Request.Path + QueryString.Create(
Request.HasFormContentType ? Request.Form.ToList() : Request.Query.ToList());
}
// Retrieve the user principal stored in the authentication cookie.
// If it can't be extracted, redirect the user to the login page.
var result = await HttpContext.AuthenticateAsync(IdentityConstants.ApplicationScheme);
if (result is null || !result.Succeeded)
{
// If the client application requested promptless authentication,
// return an error indicating that the user is not logged in.
if (request.HasPrompt(Prompts.None))
{
return Forbid(
authenticationSchemes: OpenIddictServerAspNetCoreDefaults.AuthenticationScheme,
properties: new AuthenticationProperties(new Dictionary<string, string>
{
[OpenIddictServerAspNetCoreConstants.Properties.Error] = Errors.LoginRequired,
[OpenIddictServerAspNetCoreConstants.Properties.ErrorDescription] = "The user is not logged in."
}));
}
return Challenge(
authenticationSchemes: IdentityConstants.ApplicationScheme,
properties: new AuthenticationProperties
{
RedirectUri = "Home"
});
}`
I have 3 projects:
Net Core 3.1 MVC project.
Net Core 3.1 Web Api project with JWT auth --> connected to db via Entity Framework
(Xamarin app that also uses the web api for authentication and data retrieval).
I do not want to connect separately to the same db from both projects (1,2) (does not feel like a good idea, correct me if im wrong, would like to keep the db crud operations contained to the web api).
I want to do the authentication in the Web Api project and pass the token to the Net Core MVC project.
I do not know how to use the token to authorize this user for the MVC
project, so that controllers can be accessed based on the user's role
etc. Basically log this user in in the MVC project with the token
obtained in the web api. Is this even possible or a proper method? Any
help please?
MVC project
Startup.cs class
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
// add for razor pages and refresh without rebuilding
services.AddRazorPages().AddRazorRuntimeCompilation();
// add httpClient
services.AddHttpClient();
// start auth jwt
services.AddSession(options => {
options.IdleTimeout = TimeSpan.FromMinutes(1);
});
//services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
//Provide a secret key to Encrypt and Decrypt the Token
var SecretKey = Encoding.ASCII.GetBytes
("mySecretKeyForAuthenticationAndAuthorization");
//Configure JWT Token Authentication
services.AddAuthentication(auth =>
{
auth.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
auth.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(token =>
{
token.RequireHttpsMetadata = false;
token.SaveToken = true;
token.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
//Same Secret key will be used while creating the token
IssuerSigningKey = new SymmetricSecurityKey(SecretKey),
ValidateIssuer = true,
//Usually, this is your application base URL
ValidIssuer = "https://myAzureWebAPi.azurewebsites.net",
ValidateAudience = true,
//Here, we are creating and using JWT within the same application.
//In this case, base URL is fine.
//If the JWT is created using a web service, then this would be the consumer URL.
ValidAudience = "https://mylocalhost/",
RequireExpirationTime = true,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero
};
});
// end auth jwt
// add for roles authorization
services.AddAuthorization(config =>
{
config.AddPolicy(Policies.Admin, Policies.AdminPolicy());
config.AddPolicy(Policies.Client, Policies.ClientPolicy());
});
services.AddControllersWithViews();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
//add for jwt
app.UseCookiePolicy();
app.UseSession();
//Add JWToken to all incoming HTTP Request Header
app.Use(async (context, next) =>
{
var JWToken = context.Session.GetString("JWToken");
if (!string.IsNullOrEmpty(JWToken))
{
context.Request.Headers.Add("Authorization", "Bearer " + JWToken);
}
await next();
});
app.UseRouting();
// added for jwt
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{area=Client}/{controller=LoginPage}/{action=Index}/{id?}");
});
}
}
MVC LoginPageController.cs
[Area("Client")]
public class LoginPageController : Controller
{
private readonly IHttpClientFactory _clientFactory;
public LoginPageController(IHttpClientFactory clientFactory)
{
_clientFactory = clientFactory;
}
public IActionResult Index()
{
return View();
}
[HttpPost]
public async Task<IActionResult> Login([Bind] LoginModel loginModel)
{
var client = _clientFactory.CreateClient();
//var client = new HttpClient();
try
{
var json = JsonConvert.SerializeObject(loginModel);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var outcome = await client.PostAsync("https://<AzureWebAPiUrl>/api/accounts/login", content);
if (outcome!= null && outcome.IsSuccessStatusCode)
{
var jsonResult = await outcome.Content.ReadAsStringAsync();
var token = JsonConvert.DeserializeObject<Token>(jsonResult);
Console.WriteLine(token.user_role);
// store token in a session
HttpContext.Session.SetString("JWToken", token.access_token);
// Here is the problem, once I have the token how do I make this user be
//authenticated in the mvc project so that the [Authorize[Role = "someRole"] on controllers works
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return RedirectToAction("Index", "AdminDeals", new { area = "Admin"}); // only if role is admin
}
}
Hey I have solution for this please refer below point
first of all you need to add authentication. public void ConfigureServices(IServiceCollection services)
services.AddSession();
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = >JwtBearerDefaults.AuthenticationScheme;
options.DefaultAuthenticateScheme = >JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
// Adding Jwt Bearer
.AddJwtBearer(options =>
{
options.SaveToken = true;
options.RequireHttpsMetadata = false;
options.TokenValidationParameters = new TokenValidationParameters()
{
ValidateIssuer = true,
ValidateAudience = true,
ValidAudience = Configuration["JWTConfig:ValidAudience"],
ValidIssuer = Configuration["JWTConfig:ValidIssuer"],
IssuerSigningKey = new >SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JWTConfig:Secret"]))
};
});
After that you have to Use Session for storing authentication token and in this token you have to encrypt token combination of role list whatever role want to pass for the authorization.
Here i have used JWT Bearer token
Using this session you have to configure in public void Configure(IApplicationBuilder app, IWebHostEnvironment env)startup.cs file for use header authentication.
app.UseSession();
app.Use(async (context, next) =>
{
var token = context.Session.GetString("Token");
if (!string.IsNullOrEmpty(token))
{
context.Request.Headers.Add("Authorization", "Bearer " + token);
}
await next();
});
then after you you have to add in your controller
[Authorize(Roles = "Employee,Student")]
public ActionResult Leave()
{
// your code here
}
This is a typical scenario that you should implement OAuth2.0 for your application- You have 2 kinds of clients (MVC and Xamrin), both of them need to be authenticated then access your API project, your API should be protected by a identity provider instead of doing the authenticate by itself. In asp.net core, the most popular solution is Identity Server 4, you don't have to reinvent the wheel , just create an Identity Provider sever, and config your API and MVC project based on the instruction in their documents and everything is ok then. Meanwhile, Identity Server 4 support entity framework
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.
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
});
}
}
Let's say i'm already send the custom authentication data from my client and retrieve the ss-id from the service stack Web API.
var client = new JsonServiceClient("http://somewhere/API");
var response = client.Post(new Auth() {UserName = "myuser", Password = "password123"});
and then I try to access another API function with [Authenticate], but it always fail with 401 not authorize.
public class UsersServices : Service
{
public UsersRepository Repository { get; set; }
//cannot access this...
[Authenticate]
public object Get(Users user)
{
return RequestContext.ToOptimizedResultUsingCache(
base.Cache, UrnId.Create<Users>("requestAll"), () =>
{
var data = Repository.GetAllUsers();
return data;
});
}
}
How I can access the API on the client side after the authentication?
Use SetCredentials to pass auth info with each client request.
var client = new JsonServiceClient("http://somewhere/API");
client.SetCredentials("myuser","password123");
var response = client.Get<ResponseDTO>();