Identity server 4 : custom token generation - identityserver4

Is there any way to override identity server 4 token generation ? means a class or interface to get username and password to call an external services to get token then use it by identity server 4 ?

If I understand your question correctly then Yes, there are a couple of options.
You can create a custom ProfileService to call your external service when Claims are generated, you can then fetch data from you external service, then return a List<Claim> for the information you are interested in. You would write all that inside the GetProfileDataAsync(ProfileDataRequestContext context) method.
Then you register the profile service through identity server builder middleware
var identityServerBuilder = services.AddIdentityServer();
identityServerBuilder.AddProfileService<ProfileService>()
And when you use the access token i.e communication to a third party API, you can simply depend on HTTPContext to find a claim by name and get the value you need, i usually write a ClaimsProvider that has getter methods to return the claims i need and means i can mock it easily without having to consider mocking httpcontext. Something like this
It is possible to hook into the other parts of the lifecycle, check this for example: http://docs.identityserver.io/en/latest/topics/custom_token_request_validation.html I recommend that you read the documentation if this doesn't move you forward?
Have fun! :)

Related

How to configure external authentication schemes after service startup

I want to roll my own instance of identityserver4 as authentication instance for a service I am hosting in the cloud.
My concrete scenario is that I want to be able for customers to set up using their ADFS in a self service manner similar to how slack, expensify or namely allow this.
I know how federating works. Usually in the Startup in ConfigureServices you add the following
services.AddAuthentication()
.AddCookie("cookie")
.AddSaml2p("idp1", options => {
.....
.AddSaml2p("idp3", options => {
and so on and I can use the same of the scheme to later challenge the external ADFS. But this is only and always happening at the startup of the service. When a customer is configuring the connection to his ADFS later my service is already up and running and I don't want to restart my service to be able to configure the federation between my identityserver and the external provider.
Is there a way to configure this without restarting the service?
There's 2 options as I see it:
https://www.identityserver.com/documentation/dynamic-authentication-providers
OR - as I had to a couple of years ago before anything like the above existed - creating your own version of the authentication handler (surprisingly few changes required) to accept parameters via the properties passed to ChallengeAsync(). In the case of OIDC all I needed to override was the authority URL and client ID since it's I'm only using id_token.

Google Cloud Endpoints v2: Any way to inject User?

I'm new to Google Cloud Endpoints and I am currently looking for an alternate way to receive the User method parameter.
In the documentation on Authenticating Users, the only way of receiving information about the user that is shown is to receive an instance com.google.api.server.spi.auth.common.User as a method parameter.
There appears to be no annotation I can use to request this principle elsewhere other than directly on the endpoint method. This can obviously be made to work, but I am very interested in the following scenario:
/*
* in an injection provider
*/
CustomUserClass getUser(#EndpointsUser User user) throws UnauthorizedException{
if(user == null) throw new UnauthorizedException("If we're requesting the user be injected, we should reject unauthenticated requests");
//datastore code to lookup and return my representation of a user
}
/*
* in the endpoint class
*/
#Inject
CustomUserClass userProfile;
//endpoint methods here
Does anyone know how to do the above? I realize I could simply move this logic into my endpoint class, but this is a case of cross-cutting concerns and is not only bad programming, but less easily tested.
Yes, I know I can role my own solution (pun intended), but cloud endpoints is supposed to make this kind of thing easy, isn't it?
This is currently not possible, as Guice use cases weren't common when the frameworks were written. You can file a feature request.

angularJS - webapp architecture

I have to build an angularJS webapp and found many resource for best practice but there are still some questions that were not answered. I hope you can help me.
Question 1: Model
One thing is, where should i store my model and handle changes to it?
I found some different solutions but they were all for simple datastructures. I have something like User ---> Subscription ---> Device ---> HardwareReport. And this is just one branch of the datastructure tree.
My question is where should i store it so that every Controller can access the data.
Current solution:
Current solution would be, not to store the data structure but to have a service for every object type like UserService or SubscriptionService.
And every of these services handles the communication with the backend server and keeps the return value in a cache.
Downside:
If a controller needs for example all devices of the user it has to deal with all services and can't just go through the data-structure tree. What if one controller changes for example the device object of the user. How should i notify other controllers?
Question 2: lazy configure/instantiate services
Here is a part of the application.
I have an AppController, LoginController and a MapController.
And i have a BackendService which encapsulates the API-Calls and is used by UserService and SubscriptionService.
When i login into my webapp the LoginController uses the SessionService to verify the login data and receives an accessToken for the API.
This accessToken must be set in the BackendService to be added to the header.
But the BackendService is already injected in other services.
Current solution:
Just set the AccessToken from LoginController like
BackendService.setAuth(accessToken);
Because the service is singleton all other services that uses BackendService will be have the correct setup BackendService.
Downside:
I can call functions of the BackendService before setting the access token and this would result in errors.
** Alternative solution: **
I just implement a BackendServiceFactory which i can use at any time to create a new BackendService instance. So i can create the BackendService in the LoginController after login.
Downside: I have to pass this object through all my services and controller because it won't be injected by DI.
Quite long questions but i hope you can give me some suggestions how to build this app.

SharePoint Adapter for Breeze JS/Angular and the SP User Information List

The Problem
The SharePoint adapter for Breeze expects a model with a SharePoint list name and then attempts by default to access _api/web/lists/getbytitle('<DefaultResourceName>') and I have not found a way to over ride that. The problem with this behavior is that if a user who is not a site collection admin accesses the User Information List using the web/lists/ end point they will receive a 404 error. Instead, for whatever reason, regular users must access the same exact information via _api/Web/SiteUserInfoList/items.
The Question
What would be the best way to add functionality to the Breeze SharePoint adapter to get user details or a list of site users? In my existing solution I have merely changed my data context object to use $http and the _api/Web/SiteUserInfoList/itemsend point but I'd like to still be able to use Breeze's amazing filtering ability but it's not clear to me the best path to begin adding this functionality to the adapter.
With breeze you can configure specific AJAX requests using a request interceptor.
The example below changes the timeout but you could just as easily change the url.
var ajaxAdapter = breeze.config.getAdapterInstance('ajax');
ajaxAdapter.requestInterceptor = function (requestInfo) {
requestInfo.config.timeout = 5000;
// todo: examine the requestInfo.config object and change the url as-needed
}
here's the relevant code in the breeze source

How to make WPF MVVM application connect to multiple WCF Services?

I have 4 WCF services that I have developed.
Each service is responsible for something else.
Each service has a UserNamePasswordValidator, so clients need to supply credentials when connecting.
I would now like to develop my WPF client application, in an MVVM architecture.
I would like for the WPF application to load with a 'Login' screen,
where the user will input a username and password,
and then this will be passed on to the 4 clients for the 4 WCF services (all use the same username and password).
What is the best approach to doing this ?
Where are the clients located ? in the 'Model' part ? which view's model ?
The WCF Service needs to be consumed by multiple views, so I don't think I can put any of the WCF service clients in a specific Model class...
To do this, we have created a ServiceFactory class that connects to a service given its endpoint and an appropriate IClientChannel-derived interface. This assumes that you are using the WCF services directly, e.g. not via the VS-generated proxies, since you need to set the username and password values on each client channel creation.
The client channel interfaces are in an external "service library" along with the service factory, so they can be shared with the WCF service implementations and the clients. We store the credentials in a static state dictionary (though you also put it, for example, into the main resource dictionary) with the password being saved in a SecuredString for a tiny bit of extra security.
I've described the basic process for creating such a service factory on by blog:
http://blog.kutulu.org/2012/03/proxy-free-wcf-ditching-proxy.html
In our case, we perform a setup routine in App.xaml.cs that prompts for credentials and makes an attempt to call one of our services, looping until we get a successful login. That code is much more complex, but it's basically:
while (true)
{
var factory = new ChannelFactory<ITestChannel>(new WSHttpBinding("SecuredBinding"));
ITestChannel client = null;
try
{
factory.Credentials.UserName.UserName = logOnModel.UserName;
factory.Credentials.UserName.Password = logOnModel.Password;
var address = Settings.Default.TestServiceUrlBase));
client = factory.CreateChannel(address);
break;
}
// Catch various exceptions here.
}
The trick here is that, if your login or password is wrong and your UsernamePasswordValidator fails your login, you'll get a MessageSecurityException which will fault your channel, so you'll need to close it and open a new one. But you cannot change the credentials on a ChannelFactory once you've opened the first channel, so you need to dispose and re-create a new factory and new client channel every time.
We also check for CommunicationException and ArgumentException here in case the URL is wrong.
Once that's done, you can use similar code in your service factory class to construct a client, given its channel interface, and set up the credentials for each call. (We actually cache the service factories for each distinct interface because we create and destroy channel frequently, but that's up to you.)

Resources