I'm a little confused with the session documentation, so let's say i'm already send the authentication data from the client side and retrieve the ss-id and ss-pid like this:
var client = new JsonServiceClient("http://somewhere/theAPI/");
var response = client.Post(new Auth() {UserName = "myuser", Password = "password123"});
var myCookie= client.CookieContainer.GetCookies(new Uri("http://somewhere/theAPI"));
how I can retrieve the AuthSession information just like the surname, email, etc from the servicestack? do i need it store somewhere else like in memcache server, and retrieve from that?
or I need to build my authentication in the client side? and just use the API to retrieve the data?
Assuming you've already created a custom AuthUserSession, for example:
/// <summary>
/// Create your own strong-typed Custom AuthUserSession where you can add additional AuthUserSession
/// fields required for your application. The base class is automatically populated with
/// User Data as and when they authenticate with your application.
/// </summary>
public class CustomUserSession : AuthUserSession {
public string CustomId { get; set; }
}
And you've registered your custom AuthUserSession when configuring the AuthFeature plugin, like so:
public override void Configure(Container container)
{
//Register all Authentication methods you want to enable for this web app.
Plugins.Add(new AuthFeature(
() => new CustomUserSession(), //Use your own typed Custom UserSession type
new IAuthProvider[] {
new CredentialsAuthProvider(), //HTML Form post of UserName/Password credentials
// and any other auth providers you need
}));
}
Then you can expose this data to the client in a service you create. SocialBotstrapApi provides access to the current session information on the server like this: Use it as a model to create a UserAuth service that returns the information for just the current user.
public abstract class AppServiceBase : Service {
private CustomUserSession userSession;
protected CustomUserSession UserSession {
get {
return base.SessionAs<CustomUserSession>();
}
}
}
[Route("/userauths")]
public class UserAuths
{
public int[] Ids { get; set; }
}
public class UserAuthsResponse
{
public UserAuthsResponse()
{
this.Users = new List<User>();
this.UserAuths = new List<UserAuth>();
this.OAuthProviders = new List<UserOAuthProvider>();
}
public CustomUserSession UserSession { get; set; }
public List<User> Users { get; set; }
public List<UserAuth> UserAuths { get; set; }
public List<UserOAuthProvider> OAuthProviders { get; set; }
}
//Implementation. Can be called via any endpoint or format, see: http://servicestack.net/ServiceStack.Hello/
public class UserAuthsService : AppServiceBase
{
public object Any(UserAuths request)
{
var response = new UserAuthsResponse {
UserSession = base.UserSession,
Users = Db.Select<User>(),
UserAuths = Db.Select<UserAuth>(),
OAuthProviders = Db.Select<UserOAuthProvider>(),
};
response.UserAuths.ForEach(x => x.PasswordHash = "[Redacted]");
response.OAuthProviders.ForEach(x =>
x.AccessToken = x.AccessTokenSecret = x.RequestTokenSecret = "[Redacted]");
if (response.UserSession != null)
response.UserSession.ProviderOAuthAccess.ForEach(x =>
x.AccessToken = x.AccessTokenSecret = x.RequestTokenSecret = "[Redacted]");
return response;
}
}
Related
I'm working with a very weird endpoint,
Now the data I post to my endpoint is the scorecardId and the DashboardConfig and the rest of my data is populated via the backend, which is the UserId and the DateCreated, Now I need to do a get request for the specific user and I did something like this:
#region Public Methods
[HttpGet]
[Route("GetbyUserID")]
[ValidateModel]
public IHttpActionResult GetbyUserID(Guid UserID)
{
UserID = this.GetUserId();
var config = _prefentialDashboardConfigService.GetByUserID(UserID);
return Ok(config);
}
My model:
public Guid ScorecardId { get; set; }
public Guid UserId { get; set; }
public DateTime DateCreated { get; set; }
public string DashboardConfig { get; set; }
My CRUD:
public PrefentialDashboardConfig GetByUserID(System.Guid UserId, params string[] includes)
{
return Repository.SingleOrDefault<PrefentialDashboardConfig>(config => config.UserId == UserId, includes);
}
}
My ICRUD:
T SingleOrDefault<T>(Expression<Func<T, bool>> where, params string[] includes) where T : class;
And in my front end I just called the get request but it gives me a 404 resource not found error. I call my end point like this in knockout:
var test = PreferentialProcurementDashboardApi.GetbyUserID();
//For testing purposes
console.log("You got it right!" + JSON.stringify(test));
What would be the best way to get my data to the frontend console by the UserId which is taken from my backend?
only guessing, you are probably not passing the UserId when you are doing the http get request.
var test = PreferentialProcurementDashboardApi.GetbyUserID();
probably should be
var test = PreferentialProcurementDashboardApi.GetbyUserID(5);
check the network tab in the browser dev tools to make sure that there are parameters are being passed to the backend
I have a webApi and an MVC application.
The webApi has all the logic and the MVC application is just the presentation.
Im using RestSharp to get the data from the WebApi to the MVC application.
Im sharing here one method that retrieves all user information
public IUser getUserInformationLogin(string palsoftID)
{
var request = new RestRequest("FrontDeskLog/GetUserInfo/{PalsoftID}", Method.POST) { RequestFormat = DataFormat.Json };
request.AddParameter("PalsoftID", palsoftID, ParameterType.UrlSegment);
var response = service.Execute<User>(request);
return response.Data
}
everything is good until I add Serialize attribute to the User class, I need to make User serializable in order to use session state StateServer for my MVC application.
But after adding the serialize attr the above method always returns null.
If I debug i can see that in the Response. Content all data is there, but response.data returns a null object.
Any help will be very appreciated.
The Method in the webApi is this one
public IUser GetUserInfo(string PalsoftID)
{
FrontDeskDb data = new FrontDeskDb();
return data.getUsersInfo(PalsoftID);
}
this is the class Roles
public class Roles
{
public int RoleID { get; set; }
public string Role { get; set; }
public bool Main { get; set; }
}
Thank you.
I am recently starting to learn mobile development for my Final Year Project, and I am doing an Android application using Xamarin.Android and Azure Mobile Services.
I have created a Test DB and created one entry there, trying to make my Android App to connect to the DB and retrieve this entry. I am doing this to get an idea how to establish a connection and retrieve data, and from there I will start modification properly.
That is how my Model class look like (note that JSON properties are named exactly like the columns names in my DB.
using Newtonsoft.Json;
namespace com.parkkl.intro.Models
{
class TestTable
{
public int Id { get; set; }
[JsonProperty(PropertyName = "UserName")]
public string UserName { get; set; }
[JsonProperty(PropertyName = "deleted")]
public bool Deleted { get; set; }
[JsonProperty(PropertyName = "version")]
public string Version { get; set; }
[JsonProperty(PropertyName = "createdAt")]
public string Creation { get; set; }
[JsonProperty(PropertyName = "updatedAt")]
public string Updated { get; set; }
}
}
And that is how my activity look like
using Android.App;
using Microsoft.WindowsAzure.MobileServices;
using Android.OS;
using com.parkkl.intro.Models;
using System.Collections.Generic;
using Android.Widget;
namespace com.parkkl.intro
{
[Activity(Label = "ParkKL", MainLauncher = false, Icon = "#drawable/icon")]
public class MainActivity : Activity
{
#region Variables
public static MobileServiceClient client = new MobileServiceClient
(#"http://parkkl.azurewebsites.net/");
private IMobileServiceTable<TestTable> test = null;
private List<TestTable> testItems;
#endregion
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
test = client.GetTable<TestTable>();
testItems = new List<TestTable>();
GetData();
}
public async void GetData()
{
var collection = await test.Where(user => user.Id == 1).ToCollectionAsync();
foreach (var item in collection)
{
testItems.Add(
new TestTable
{
Id = item.Id,
UserName = item.UserName,
Deleted = item.Deleted,
Version = item.Version,
Creation = item.Creation,
Updated = item.Updated,
});
}
var finalItem = collection[0];
TextView text = (TextView)FindViewById(Resource.Id.TextFromDB);
text.Append(finalItem.UserName);
}
}
}
Now the issue is, every time I try to deploy the app, it throws this exception
Microsoft.WindowsAzure.MobileServices.MobileServiceInvalidOperationException:
You must be logged in to use this application
In my App Service in Azure, I have disabled all authentications, still I get this error. I am wondering where the issue is coming from?! I will much appreciate your help.
EDIT: I guess I found the issue, which was the permissions given on the table itself. However, I am still finding out a way to authenticate my app properly
Check out the book http://aka.ms/zumobook for details on how to deal with authentication.
I am familiar with roles and authentication attributes in MVC, but as I am adding more and more information onto my database I think I ma going to run into a problem with primary keys being unencrypted or accessible.
I am using identity 2.1, so when a user is logged in I have access of their UserId and their CustomerID but my concern is that any user can go to /Customers/Delete/3 or any CustomerID and have access. Even if I created a GUID id or other encryption it could still be vulnerable to brute force attacks.
Is there a way in MVC to implement a check to only allow the current user to load pages that are related to them?
You can add extra field say "CreatedByUserId" to database table and when user access page check if CreatedByUserId matches with user id of logged in user or not.
You should be checking if the current logged in user has access to any of the information before you try and manipulate data. For example...
public async Task<HttpResponseMessage> DeleteCustomer(string customerId)
{
var appUser = await _authRepository.FindUser(User.Identity.GetUserName());
if(!_customerRepository.CanDeleteCustomer(appUser.Id, customerId){
return BadRequest();
}
// they have access so do what you need to do down here..
}
You can create a custom Authorize Attribute and a table in the database in which you store which user is allowed what Pages (Actions) or Controllers and then check that table while authorizing that whether the user is authorized for that Page/Controller. I have created an example for you in which I used Custom Authorize Attribute named MyAuthorizeAttribute and a database table named PageRoles.
Custom Authorize Attribute:
public class MyAuthorizeAttribute : AuthorizeAttribute
{
readonly ApplicationDbContext _db = new ApplicationDbContext();
string _pageName;
public MyAuthorizeAttribute(string pageNameFromController)
{
_pageName = pageNameFromController;
}
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
var userId = httpContext.User.Identity.GetUserId();
var pageRoles = db.PageRoles.Where(m => m.UserId == userId);
foreach (var item in pageRoles)
{
if (item.PageName == _pageName && item.UserId == userId)
{
return base.AuthorizeCore(httpContext);
}
}
return false;
}
}
Model used:
public class PageRole
{
public int Id { get; set; }
public string UserId { get; set; }
public string PageName { get; set; }
public virtual ApplicationUser User { get; set; }
}
and then you will just have to use the attribute on your controllers just like you use Authorize attribute:
[MyAuthorize("Home")]
public class HomeController : Controller
{ }
I am trying to implement Oauth 2.0 security integration with Asp.net web api 2 but only with external logins like google.I am pretty new for Oauth thing.
Can any one suggest any good tutorial/ example with only external login.
I do not want local user to register etc.
Google describes all the options pretty well on their website Using OAuth 2.0 to Access Google APIs
The most important steps are:
Register your application at Google Developer Console
Enable all your required scopes
Specify the allowed callback url to your website
Basically it works like this:
You redirect the user to your /api/Account/Login page
This Action method will redirect the user to the Google login page
User logs in and gets redirected to the callback url you specified (and approved in the Developer Console)
This callback url Action method will ask Google for a token based on the authorization code.
Following code snipped should get you started:
[RoutePrefix("api/Account")]
public class AccountController : ApiController
{
private readonly string _clientId = "YourCliendId";
[Route("Login")]
public HttpResponseMessage GetLogin()
{
string scope = HttpUtility.UrlEncode("Space Seperated list of scopes");
string redirectUri = HttpUtility.UrlEncode("http://YourWebsiteURL/api/Account/OAuthCallback");
string accessType = "Either online or offline";
string requestUri = string.Format("https://accounts.google.com/o/oauth2/auth?response_type=code&client_id={0}&redirect_uri={1}&scope={2}&access_type={3}&approval_prompt=auto&include_granted_scopes=true", _clientId, redirectUri, scope, accessType);
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.MovedPermanently);
response.Headers.Location = new Uri(requestUri);
return response;
}
[Route("Logout")]
public HttpResponseMessage GetLogout()
{
//Optionally if you need to be able to logout...
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Moved);
response.Headers.Location = new Uri("https://accounts.google.com/logout");
return response;
}
[Route("OAuthCallback")]
public HttpResponseMessage GetOAuthCallback(string error)
{
//This would be a nice place to include some logging...
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Moved);
response.Headers.Location = new Uri("http://YourWebsiteURL");
return response;
}
[Route("OAuthCallback")]
public HttpResponseMessage GetOAuthCallback(string code, string scope)
{
string redirectUri = HttpUtility.UrlEncode("http://YourWebsiteURL/api/Account/OAuthCallback");
string postMessage = string.Format("code={0}&client_id={1}&client_secret={2}&redirect_uri={3}&grant_type=authorization_code", code, _clientId, "YourGoogleSecretCode", redirectUri);
string jsonMessage;
using (WebClient client = new WebClient())
{
//Convert the authorization code to a token
client.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded; charset=utf-8";
jsonMessage = client.UploadString("https://accounts.google.com/o/oauth2/token", "POST", postMessage);
}
Token token = JsonConvert.DeserializeObject<Token>(jsonMessage);
//Do something with the token. E.g. put it in a cookie / header ... and pass it to the client.
}
}
public class Token
{
[JsonProperty("access_token")]
public string AccessToken { get; set; }
[JsonProperty("expires_in")]
public int ExpiresIn { get; set; }
[JsonProperty("token_type")]
public string TokenType { get; set; }
}
public class TokenInfo
{
[JsonProperty("issued_to")]
public string IssuedTo { get; set; }
[JsonProperty("audience")]
public string Audience { get; set; }
[JsonProperty("user_id")]
public string UserId { get; set; }
[JsonProperty("scope")]
public string Scope { get; set; }
[JsonProperty("expires_in")]
public int ExpiresIn { get; set; }
[JsonProperty("email")]
public string Email { get; set; }
[JsonProperty("verified_email")]
public bool VerifiedEmail { get; set; }
[JsonProperty("access_type")]
public string AccessType { get; set; }
}
BTW. If you need to later on validate the token you can use the following code:
string requestUri = string.Format("https://www.googleapis.com/oauth2/v1/tokeninfo?access_token={0}", token.AccessToken);
string tokenInfoMessage;
using (WebClient client = new WebClient())
{
tokenInfoMessage = client.DownloadString(requestUri);
}
TokenInfo tokenInfo = JsonConvert.DeserializeObject<TokenInfo>(tokenInfoMessage);
//Don't forget to validate the Audience and Scope, because the token might be a valid token (but not meant for your website).
if (tokenInfo.Audience == _clientId && tokenInfo.Scope.Contains("All the scopes that you provided") && tokenInfo.UserId == "TheGoogleUserIdYouWantToCheck")
{
//Looks valid, so continue with whatever you want to do...
}