Programatically create an OpenID Connect id_token with IdentityServer3 - identityserver3

I am adding IdentityServer3 on to an existing website (NopCommerce to be specific). It has it's own registration and authentication system, but we need to also offer OpenID Connect so that a back end application can be integrated. Calls to the back end need to have an id_token for the current user that the back end validates to confirm the identity.
I've found information about how to use an existing membership database to provide the user data for IdentityServer3 to check, however I am bit stuck on how to generate the id_token for each user. I guess the obvious answer is to replace the website login with IdentityServer, however that raises further issues for the rest of the project. Ideally I'd like the user to log in as normal and then call a method in IdentityServer to generate the id_token.
Is this possible? I've been hunting around, but can't find anything so far. The best I found was an answer to programmatically sign in to identityserver3. I think it's suggesting making a HTTP post to IdentityServer, but it feels kind of hacky.
I also found Implementing OAuth 2.0 and OpenId Connect provider using IdentityServer3 with existing login server and membership provider, but I have to admit it's assuming quite a bit of knowledge I don't have (yet).

My solution based on John C's answer worked using a NopCommece external authentication plugin, but I was unhappy with having to leave Nop to authenticate and register when IdentityServer was using the Nop database. Going via the external auth route seemed to be the only way to get an OpenID Connect id_token. After a break and some time to revisit the code though I found the following:
https://identityserver.github.io/Documentation/docsv2/configuration/serviceFactory.html
https://identityserver.github.io/Documentation/docsv2/configuration/serviceFactory.html
By implementing custom services, IdentityServer allows you to mess with the token creation and generation AND the dependency injection system it uses gives you access to instatiated versions of the default services.
Previously I had followed an answer which sent a username and password to the token endpoint. The OpenID specs say that this should only return the access_token, which is exactly what DefaultTokenService in IdenttyService does. By adding a CustomTokenResponseGenerator however, I was able to re-use the request to create and return an id_token too.
CustomTokenResponse class:
internal class CustomTokenResponseGenerator : ICustomTokenResponseGenerator
{
protected ITokenService _tokenService;
public CustomTokenResponseGenerator(ITokenService tokenService)
{
_tokenService = tokenService;
}
public Task<TokenResponse> GenerateAsync(ValidatedTokenRequest request, TokenResponse response)
{
var tokenRequest = new TokenCreationRequest
{
Subject = request.Subject,
Client = request.Client,
Scopes = request.ValidatedScopes.GrantedScopes,
//Nonce = request.AuthorizationCode.Nonce,
ValidatedRequest = request
};
var idToken = _tokenService.CreateIdentityTokenAsync(tokenRequest);
idToken.Wait();
var jwt = _tokenService.CreateSecurityTokenAsync(idToken.Result);
response.IdentityToken = jwt.Result;
return Task.FromResult(response);
}
}
How to inject the custom service in Startup.cs:
factory.TokenService = new Registration<ITokenService, TokenService>();
factory.CustomTokenResponseGenerator = new Registration<ICustomTokenResponseGenerator, CustomTokenResponseGenerator>();

When user logs-in into NopCommerce application, you can send an HTTP authorize request to identityserver. Make sure while sending the authorize request to idsrv you are using prompt=none, this way you will get the id_token or access_token without showing a consent to the user again if the user is already logged-in.
function getAuthorizeRequest() {
var url = global.appSettings.identityServerURL
+ "/connect/authorize?client_id=siteB&response_type=id_token token&redirect_uri="
+ global.appSettings.siteBUrl + "/Main/NopCommerceapp&scope=siteBscope openid email roles&prompt=none&nonce="76767xz676xzc76xz7c67x6c76"
return encodeURI(url);}
Checkout idsrv authorize endpoint https://identityserver.github.io/Documentation/docsv2/endpoints/authorization.html

I think your best solution would be to implement IdentityServer3 and get it reading from your existing Nop membership database. Then create a Web API app that runs on its own that utilizes your IdentityServer3 setup. Inside the Web API, you implement all the functionality that your back end app needs, reading and writing to the Nop database.
Keep your Nop frontend UI separate from your backend API. If you follow the two links below, you should be able to get something up and running pretty quickly.
Creating the simplest OAuth2 Authorization Server, Client and API
MVC Authentication & Web APIs

Related

Identity Server Resource Owner flow with external Identity Provider

We have a project where the client requests the use of their own Identity Provider, in this case, it is SalesForce.
We secure the application using IdentityServer 3 and have configured it that for this client (based on parameters) it will use SalesForce as the IDP.
For the web app, no problem, Identity Server redirects to the Sales Force login page and everything works great.
Now we have a mobile app to build and the client would like to avoid having a web login page and would rather have a nice polished login form built in the application. This means that we will have to use the Resource Owner flow.
Now, the users creds are on SalesForce side so how does that work and is this at all possible in IdentityServer 3 ?
I see 2 possibilities but I kind of like neither of them:
Send the auth call to IdentityServer which should detect that it is up to SalesForce to validate the user and forwards the request there. I think it is not good as I would rather avoid having my IdentityServer dealing with credentials that he should not even know
Send a first auth call to SalesForce to get some "id token" that would then allow me to send another auth call to IdentityServer which will then recognize the "id token" and release an access token.
That seems like a stretch and forces the app to know that there is an IDP which is none of its business.
Any idea?

Renew access token and protect static files

I have question regarding setup of access token renewal/refresh. Our Setup:
Implicit flow
Angular SPA using bearer token for API
Thin MVC frontend serving cshtml containing SPA
Short access token (10min)
20 min Idsrv cookie sliding (used as activity timeout)
The application has to apply to some strict security rules and intellectual property.
We need to renew the access token before it expires and API returns 401.
I’ve looked at the oidc-client-js to handle that. But that would remove the option of authenticating the static files like we do today, since there would no longer be a cookie for the MVC app.
Is there a way of securing them, or is that just something that we have to accept when building a SPA with OpenID Connect?
If you would like to enforce authorization on static files then this needs to be done by server-side code. Since your client is using an MVC backend, my recommendation would be to use the Hybrid Flow in conjunction with the Katana OpenID Connect middleware. You may then pass on any tokens you would like to use from the server-side code to your SPA via your view (cshtml).
The middleware required is available on NuGet:
install-package Microsoft.Owin.Security.Cookies
install-package Microsoft.Owin.Security.OpenIdConnect
The following snippet allows for configuration in your OWIN pipeline (taken and slightly altered from this tutorial):
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "Cookies"
});
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
{
Authority = "https://localhost:44319/identity",
ClientId = "mvc",
RedirectUri = "https://localhost:44319/",
ResponseType = "code id_token",
Scope = "openid offline_access",
SignInAsAuthenticationType = "Cookies"
});
Using this flow, you are no longer given tokens immediately but will need to exchange the auth code returned ("code" grant type) for a pair of tokens being the:
access_token (the one you are already receiving in implicit flow)
refresh_token (this can be used at the token endpoint to renew the access_token)
The main things to note about the above configuration are response type and scope.
Response type is no longer just asking for tokens (implicit) but now asks for code.
Scope includes "offline_access" scope which will return the refresh_token.
Like this we have solved both your access token expiry problem and have begun to solve your static asset problem by moving authorization to the back-end. To help you with the next part I would need to know how you are serving your assets as there are different ways depending on whether you are using OWIN to serve or IIS.

Symfony Restful API authentication and OAuth2

I am building a RESTful API application with Symfony2.
The app will consist of two parts.
JavaScript front-end - everything the user will ever be able to see and do will reside here.
Symfony2 back-end API - every resource and data the user will be able to reach from front-end will be served in standard JSON via endpoints.
I have never built a fully RESTful application before. My main concern is how to authenticate users.
I imagine REST authentication like this:
A user enters his credentials in a form generated in the front end, then the request is sent to the server where authentication logic happens and if the user is authenticated, a response with "token" is sent back to user, that he will add that token to every request url or authorization header (I don't know which of these options is preferable).
Then with every request, the server will check if the user token is valid and if the user is authorized to access that data (roles) and if so serves request data. (I don't want to allow users login with Google, Facebook or anything like that. I want my users logging in to other application using my app)
Now this seems quite simple, but then there's OAuth2 that got me confused because I jumped into developing without research. I downloaded FOSOAuthServerBundle and started messing around when I started to get a feeling that something is not right.
What I would like to know is the difference between RESTful authentication and OAuth.
What are the recommendations for implementing the described login mechanism?
You've got it pretty spot on. You use OAuth just for the authentication and all the following requests will have to provide that HTTP-Authorization header. You would need to create your custom authentication provider to handle that. Also use something like FOSRestBundle to create your resources.

OAuth access token for internal calls

I'm currently tyring to build an API driven symfony2 web applicaiton.Just a basic application to learn symfony2 and REST.
It would be based on a RESTful api. Calls to the API will be authenticated using OAuth.
For e.g.:
if a client application wants to get data (information about all the fruits) through API it will need to make a GET request to the url and pass the access token as a parameter.So the url will look something like this.
http://www.mysite.com/api/fruits.json?=<access token>
Now the problem is that i would be needing the same data in one of my actions as well.
I need some help here.In order to get get data from above url in one of my actions i will also need to send an access token in the url.
How do i get this access token??
Should there be a fixed token which will be used for all such calls within my application??
You basic application project will grow manifold if you try to do what you want here.
Basically, you need to implement an Authentication Server for this.
i) First, the app should be registered for a scope;
ii) Using the app the user logs in to the authentication/authorization server.
iii) The server verifies if the app has access to the scope and if the user is registered in your system.
iv) Server creates an access token (which is a HMAC signed string) and returns to your app.
v) The app then hits the endpoint (restful API) with the token.
vi) The RESTful service then internally sends the token to the server and fetches the customerID for which the call is made and performs the actions that it's supposed to.
I wrote an answer once on how to create a OAuth Service/Provider - How would an efficient OAuth2.0 server / provider work?
Also, OAuth was designed such that client apps/3rd party software can access a user's resources on his behalf. A very simple example is = An app posting something on your facebook wall on your behalf. It is actually accessing a resource that you own (the wall) and posting to it. You do not need OAuth just to get some data - there are other ways to secure the API.

REST API and client on same server, need API authentication?

First, let me describe the application: we are working on a web-based software which is some kind of custom help desk application. It requires the user to login (we use FOSUserBundle). After login the user is redirected to the dashboard. From the dashboard there is no more page reload, the frontend is build on Angularjs and the user can get anywhere within the application without page reload. You could speak of a single page application.
So the data that is presented to the user, is fetched from a rest api (we use FOSRestBundle). This works quite well at this point.
There is some kind of dilemma. Only our staff will access this application (for now). So a staff member needs to login to access the helpdesk. The data that is pushed to the frontend via angularjs is called via api, so the user that has just logged in needs to authenticate again on every request because of rest.
Problem: Since the backend runs on symfony2 let us just try to get the user object of the currently logged in user when an api call is made:
$this->get('security.context')->getToken()->getUser()
returns anon. that stands for anonymous, or
$this->getUser();
returns just null.
So the authenticated context seems to be gone when using the rest api. However when I call an action directly without rest, I can get user information.
So what we need is to secure our rest api and get user information on every api call. We don't want third party people to access our application, just staff. I am not familar with OAuth, but the user will be redirected to a third party page to Allow/Deny access to his data? This would not be an option for us.
Based on that information, do you have any suggestions or ideas how to secure the api and transport the user data so that getUser does not return null or anon. but the actuall logged in user?
there's another way to resolve your problem.
It's by using Certificates.
you can generate certificates then use Http tunneling (https obviousley), the server will ask for a certificate (you've to configure Apache for that but it's not a big challenge).
with this in place, you've to add a CertificateManageron the server side to ensure that the certificate is valid and to know who's calling the service (to be able to authenticate the user at each request), the CertificateManager(or what ever you'll call it) will probably have to be configured within you filters chaine (as known in the java world), et voilà
Hop that help you,
Abderrazak
REST is stateless so you will have to send some kind of authentication/authorization in each request. You can use HTTP BASIC AUTH or something like OAuth.
Have a look at https://github.com/FriendsOfSymfony/FOSOAuthServerBundle
I'm kind of building our application in exactly the same architecture (RESTful API with Symfony2 back-end and AngularJS frontend.
Another way is to duplicate the api routes, so that you have the api routes protected by OAUTH and the api routes protected by the session, both of them pointing to the same controllers. The method was explained here: https://stackoverflow.com/a/22964736/435026