req.GetApiKey() doesn't execute any query in DB ServiceStack ApiKeyAuthProvider - servicestack

Here is my auth config
Plugins.Add(new AuthFeature(() => new AuthUserSession(),
new IAuthProvider[]
{
new ApiKeyAuthProvider(AppSettings) {RequireSecureConnection = false }
})
{
IncludeRegistrationService = true,
});
Global filter
GlobalRequestFilters.Add((req, res, requestDto) =>
{
LastApiKey = req.GetApiKey();
});
I have generated Api key in DB and trying to pass the key through postman or JsonServiceClient with Basic Authentication having API key in Username of Http request. I tried to pass bearer token in Http request too but not able to get api key from req.GetApiKey(). When I see through SQL profiler it doesn't show any query executed. However I am able to resolve IManageApiKeys and able to execute it's methods. Do I need any attribute in my service or any additional configuration in AppHost?

ServiceStack's API Key Auth Provider works by setting up an Authenticated User Session on the Request for successful API Key Authentication requests. When setting up the Authenticated User Session the API Key that was used to authenticate is stored in IRequest.Items Dictionary which is what IRequest.GetApiKey() Extension method is returning.
So IRequest.GetApiKey() isn't making any DB calls, that was already done initially when setting up the Authenticated User Session.
Authentication is performed when it's required, e.g. when your Services are annotated with any of the Authentication Attributes below:
[Authenticate]
[RequiredRole] / [RequiresAnyRole]
[RequiredPermission] / [RequiresAnyPermission]

Related

Keycloak-connect with express, is there a simple Keycloak login method

I am using Keycloak-connect, the Keycloak adapter for nodejs. In my express app, there is an app.post('/routes/login') endpoint that the login form posts to. In that endpoint there is an authentication method that I am trying to replace with Keycloak. That method just takes the username and password (and request and response object), authenticates, and returns true if the authentication was successful. Is there an equivalent I can use in the Keycloak-connect-api? I was looking but the documentation was rather poor for that adapter.
In the end I am trying to use my own login page to log in to Keycloak.
Maybe with Keycloak.grantmanager.obtainDirectly ?
You can use
keycloak.grantManager.obtainDirectly(username, password) like that way and return the token to client.
or you can use rest api provided by keycloak
let tokenObject = await axios.post(`http://localhost:8080/auth/realms/${realmName}/protocol/openid-connect/token`, requestBody );
if(tokenObject.status === 200){
accessToken = tokenObject.data.access_token;
}

Xamarin MobileServiceClient RefreshUserAsync with Google 403

I am using Azure's MobileServiceClient sdk to authenticate with my server. With the upgrades to 4.x version I am also using Xamarin.Auth to authenticate users with Google and Facebook. When the response comes back from Google I am getting a refresh token. I then call the mobile service sdk like so:
var accessToken = account.Properties["access_token"];
var idToken = account.Properties["id_token"];
var zumoPayload = new JObject();
zumoPayload["access_token"] = accessToken;
zumoPayload["id_token"] = idToken;
var user = await client.LoginAsync(MobileServiceAuthenticationProvider.Google, zumoPayload, );
This work perfectly fine. What does not work is the call to client.RefreshUserAsync(). That is throwing a 403 every time saying the refresh token is either expired or no longer valid even when I call that method right after I logged in. I do not see many examples at all using the MobileServiceClient 4.x sdk and none of them have examples of how to use the refresh token.
I have tried sending that upin the zumo payload as well but it does not work. I have tried invalidating my user on Google (I am getting the refresh token back), tried logging in through the browser and going to auth/me but the refresh token is not there. Any help would be great!
AFAIK, you could leverage the Xamarin.Auth SDK to independently contact the identity provider and retrieve the access token on your mobile client side, then you need to login with your backend (azure mobile app) along with the token for retrieving the authenticationToken, then you could leverage the authenticationToken to access the resources under your mobile app.
Since you are using Client-managed authentication, for refreshing the new access_token, you need to do it on your mobile client side. I checked Xamarin.Auth and found that there is no method for requesting an access token. You need to refer to Refreshing an access token and implement this feature by yourself. I followed OAuth2Authenticator.cs and created a extension method for requesting an access token as follows:
public static class OAuth2AuthenticatorExtensions
{
public static Task RefreshAccessTokenAsync(this OAuth2Authenticator authenticator, Account account)
{
var dics = new Dictionary<string, string>
{
{"refresh_token",account.Properties["refresh_token"]},
{"client_id", authenticator.ClientId},
{"grant_type", "refresh_token"}
};
if (!string.IsNullOrEmpty(authenticator.ClientSecret))
{
dics["client_secret"] = authenticator.ClientSecret;
}
return authenticator.RequestAccessTokenAsync(dics).ContinueWith(task =>
{
if (task.IsFaulted)
{
//todo:
}
else
{
authenticator.OnRetrievedAccountProperties(task.Result);
}
});
}
}
Additionally, if you leverage Server-managed authentication with Microsoft.Azure.Mobile.Client, then you could leverage RefreshUserAsync for refreshing the access token, at this point your previous access_token, clientId are stored on azure, and your mobile app backend would directly communicate with Google's OAuth 2.0 endpoint and request a new access token for you and update the token store on Azure. For more details about token store within App Service, you could follow here.

Authenticate server to server communication with API key

I have a couple of self-hosted windows services running with ServiceStack. These services are used by a bunch of WPF and WinForms client applications.
I have written my own CredentialsAuthProvider. My first implementation of the user database was on MSSQL server using NHibernate. Now since the system is growing I reorganize things a bit. I have created a central 'infrastructue' service which uses Redis as data store and is responsible for account management, central configuration and preferences management. Later it will also contain central logging and RedisMQ. All accounts, roles etc are now stored there (instead of MSSQL). Account migration was successfuly and authentication works fine so far.
Now I have the problem, that clients and servers need to get and set their configurations / preferences. This means that my servers are also clients since they not only serve client requests for their specific business domain but itself need to call the 'infrastructure' server to load / update its own configuration and later log entries and messages.
To authenticate such requests I thought an API key is a good way to go. These requests are not user related and therefore do not need a gateway functionality, they simply need some communication with the central infrastructure server. So I was reading the ServiceStack docs about the API Key Provider, but unfortunately for me a lot remains unclear.
Here first some relevant code from my 'infrastructure' server's Configure method:
private PooledRedisClientManager RedisBusinessPool { get; set; }
//...
container.Register<IRedisClientsManager>(c => new PooledRedisClientManager(connStrBus));
container.Register(c => new AppUserRepository(RedisBusinessPool));
Plugins.Add(new AuthFeature(() => new AuthUserSession(),
new IAuthProvider[] {
new BediCredentialsAuthProvider(),
}
));
// For the API keys I tried:
Plugins.Add(new AuthFeature(() => new AuthUserSession(),
new IAuthProvider[] {
new ApiKeyAuthProvider(AppSettings)
{
KeyTypes = new []{"secret", "publishable"},
},
}
));
Since I enabled the API Key plugin I get an error on the client when I try to login:
ERROR; AccountManagerWinDesktop; [LoginViewModel+<Login>d__50.MoveNext]; - <username> failed to login to server <myInfrastructureServer>. Exception: 404 NotFound
Code: NotFound, Message: No configuration was added for OAuth provider 'credentials'
Does this mean, that I have to implement my own ApiKeyProvider to cooperate with my implementation of the CredentialAuthProvider? If so, what do I need to add?
In my CredentialAuthProvider implementation I have overwritten Logout, Authenticate, OnAuthenticated and TryAuthenticate. A WPF client offers a UI to store users and roles. They are stored on the Redis database including hashed passwords etc. In my TryAuthenticate implementation I simply have:
public override bool TryAuthenticate(IServiceBase authService, string userName, string password)
{
AppUser user = null;
try
{
//the repository handles all Redis database access
var userRepo = HostContext.TryResolve<AppUserRepository>();
user = userRepo.GetAppUser(userName);
if (user == null)
throw HttpError.NotFound("User '{0}' not found. Please try again.".Fmt(userName));
authService.Request.Items.Add("AppUser", user);
var pwdMgr = new PwdManager();
var hpwd = pwdMgr.GetHashedPassword(password, user.Salt);
if (hpwd == user.Password)
{
//do stuff
}
else
{
// do other stuff
}
return hpwd == user.Password;
}
catch (Exception ex)
{
Log.Error($"Error retrieving user {user} to authenticate. Error: {ex}");
throw;
}
}
What I do not understand right now - Questions:
How are API keys related to my own implementation of CredentialsAuthProvider?
How can I issue API keys to an application server? (I read that ServiceStack creates keys automatically when a user is created, but I do not need this in my scenario)
Do I also have to implement my own ApiKeyAuthProvidersimilar to the CredentialsAuthProvider I have overwritten? If so, is there a sample somewhere?
Is there any object / data model for API keys?
Do I need to implement something like the TryAuthenticate method above to verify my API Keys?
You should only ever register 1 of any Plugin type, so change your AuthFeature plugin to register all Auth Providers you want to enable, e.g:
Plugins.Add(new AuthFeature(() => new AuthUserSession(),
new IAuthProvider[] {
new BediCredentialsAuthProvider(),
new ApiKeyAuthProvider(AppSettings)
{
KeyTypes = new []{"secret", "publishable"},
},
}
));
How are API keys related to my own implementation of CredentialsAuthProvider?
An API Key is assigned to a User, i.e. when a request is received with an API Key, they're authenticated as the user the API Key is assigned to. API Keys are created for each new user that's registered, the above configuration creates a secret and publishable key for a new register created with the /register service.
API Keys requires using a User Auth Repository
Your users need to be persisted in an AuthRepository in order to use the API Key AuthProvider. The list of support Auth Repositories are listed on in the documentation. Although you can use your own custom User Auth Repository if it implements IUserAuthRepository and IManableApiKeys interfaces.
How can I issue API keys to an application server? (I read that ServiceStack creates keys automatically when a user is created, but I do not need this in my scenario)
An API Key is assigned to a User - all of ServiceStack AuthProviders revolves around Authenticating Users. One idea is to create a "User" to represent that App Server. You can use the IManageApiKeys API to create your own API Keys, there's an example of using this in the code-snippet for creating API Keys for existing Users.
Do I also have to implement my own ApiKeyAuthProvider similar to the CredentialsAuthProvider I have overwritten? If so, is there a sample somewhere?
You wont need to implement anything to use the existing ApiKeyAuthProvider but if it doesn't do what you need you can take ApiKeyAuthProvider.cs and create a customized version that does what you need.
Is there any object / data model for API keys?
The ApiKey class is the model that contains the API Key itself, which is persisted in all supported Auth Repositories.
Do I need to implement something like the TryAuthenticate method above to verify my API Keys?
No.

Custom authorization with Azure AD Authentication in OWIN Web API

We are using Azure AD authentication for one of our client application. We want to implement claims based authorization along with it.
Our application set up is Angular Based client app connecting with Web API (both client server secured using Azure AD Bearer Authentication). Server application is hosted using OWIN.
We need to provide custom authorization on server side. There is a provision in Azure AD for adding users and roles. However, that is not enough for us. Our user management is through AD & Security Groups. To gain access to application, users need to part of a base group and further rights (access particular section of application, edit a specific entity etc.) are assigned based on additional groups or given directly to users in the application. Essentially, not all users will be registered in the application and we may have to query the AD using graph API to check which all application specific groups they belong.
OWIN authentication and authorization model is based on Authentication Server and Resource server. We can separate them on need basis. However, in our case, we need to split the authentication and authorization. When the client presents the bearer token, we need to verify if the token is valid and then add claims to user profile. We also need to cache the user claims so that we do not hit the database frequently. (Our client app make multiple Web API calls in one user action.)
What is the location in Identity 2.0 where
I can verify the token &
insert application specific claims
If my entire application revolves around the user authorization and all queries need to be filtered on what data the user can access, which is a more suitable design pattern for the Web API application?
I believe what you're looking for are the Authentication and Authorization filters in the ASP.NET Web API 2.0 stack.
You can implement per-web method authorization by implementing System.Web.Http.Filters.IAuthorizationFilter on an attribute class, then decorate the web action methods of your service controller with that attribute. Web API 2.0 will select a method based on URL routing, notice that there is an attribute on that method implementing IAuthorizationFilter, and will call the ExecuteAuthorizationFilterAsync method on that attribute instance before calling the web method. Placing the authorization step before the web method invocation allows invalid requests to be discarded quickly, before getting into the heavy lifting of parameter binding.
The incoming token is validated by an IAuthenticationFilter implementation which executes before the authorization step.
Documentation and examples are extremely hard to find. Here's one of the few search results that are actually relevant: http://thegrumpycoder.com/post/105427070626/secure-web-services-with-web-api-and-sitecore
you can check if this helps...
UserProfile profile = new UserProfile(); //To deserialize the response stream (JSON)
string tenantId = ClaimsPrincipal.Current.FindFirst(TenantIdClaimType).Value;
AuthenticationResult result = null;
try
{
// Get the access token from the cache
string userObjectID =
ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier")
.Value;
AuthenticationContext authContext = new AuthenticationContext(Startup.Authority, new NaiveSessionCache(userObjectID));
//use ClientID, ClientSecret
ClientCredential credential = new ClientCredential("b557ceed-xxxx-xxxx-xxxx-xxxxxxxbc240", "AXFxx//xxxxxxxxxxxxxjVFz4sqYm8NDAPEOLkU=");
result = authContext.AcquireTokenSilent("https://graph.windows.net", credential,
new UserIdentifier(userObjectID, UserIdentifierType.UniqueId));
// AcquireTokenSilent may throw exception if the cache is empty. In that case, logout the user and make him login.
string requestUrl = String.Format(
CultureInfo.InvariantCulture,
"https://graph.windows.net/cdmsdev.onmicrosoft.com/groups/b40xxxx-14a8-xxxx-9559-xxxxxxca90c8/members/?api-version=1.6");
//Above grap API url is for getting list of users who belong to a specific group (with GUID b40xxxx-1....)
HttpClient client = new HttpClient();
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, requestUrl);
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
HttpResponseMessage response = client.SendAsync(request).Result;
if (response.IsSuccessStatusCode)
{
var upn = ClaimsPrincipal.Current.Identity.Name;
string responseString = response.Content.ReadAsStringAsync().Result;
profile = JsonConvert.DeserializeObject<UserProfile>(responseString);
if (profile.Users.Contains(upn)) //check if the current user is in the list of users of the Admin group
return true;
}
}
catch (Exception e)
{
//handle authorization exception here
}
The graph API URL can be replaced with a function to check for membership of a specific group which will directly return a bool value instead of getting all users of that group.

Authorization extensions for ServiceStack

Is there any (or going to be any) built in support for declaratively securing (i.e. using attributes) REST services for oAuth2?
I would like to specify that the REST services of my SS web service can only be accessed by a client if they specify the oAuth2 'Authorization' header in their request to the service.
I don't want my service to provide authentication to my clients (i.e. no AuthFeature). Clients need to have already done authentication with a oAuth service (i.e. facebook etc.).
Using the [Authenticate] attribute on your Service ensures that only authenticated clients have access.
The Authentication wiki explains how to initialize ServiceStack's built-in AuthFeature to specify only the providers you want to allow clients to authenticate with, e.g. You can ensure clients can only Authenticate with either LinkedIn or Google OAuth2 providers with:
var appSettings = new AppSettings(); //Access Web.Config AppSettings
Plugins.Add(new AuthFeature(() => new CustomUserSession(),
new IAuthProvider[] {
new GoogleOAuth2Provider(appSettings), //Sign-in with Goolge OAuth2
new LinkedInOAuth2Provider(appSettings), //Sign-in with LinkedIn OAuth2
}));
Note: OAuth2 requires the additional ServiceStack.Authentication.OAuth2 NuGet package and Web.Config settings, see Auth docs for more info.
Using Request Filters
You can also enforce specific requirements for client requests by a Global Request Filter or opt-in Request Filter Attributes, e.g:
this.RequestFilters.Add((httpReq, httpRes, requestDto) => {
var authHeader = httpReq.Headers[HttpHeaders.Authorization];
if (!IsValidAuthHeader(authHeader)) {
httpRes.StatusCode = (int)HttpStatusCode.Unauthorized;
httpRes.StatusDescription = "Authentication is required";
httpRes.EndRequest();
}
});
More Service Restrictions
Also related are the Security docs describes how you can declaratively restrict services using the [Restrict] attribute.

Resources