The Belgian eID is a smartcard which contains the name, date of birth, address, picture of a Belgian citizen and almost everyone in Belgium has one. Now because of the nation wide availability of this card it could be interesting to use it as an authentication mechanism. The Belgian government is already making this possible through the "FAS" system, which is only available for governmental organizations. But what if you wanted to use the Belgian eID in your applications? Well, you can use the SDK available on Google Code. The downside: the Javascript SDK no longer works, so you can't use the SDK for web applications.
There are a few other ways to get this working in a browser (host the applet yourself with the IdP backend, write a good old ActiveX control which will not work on OSX/Linux, …) but none of these are solutions you really want to use in production. The only good alternative for non-governmental organizations is "e-contract", a company offering an eID Identity Provider. The person behind this company is Frank Cornelis, which is also the eID architect at FedICT. Using the IdP comes at no cost, but if you want an SLA you'll need to be a registered (paying?) customer. And they have a few big references like Digipolis and Mobistar.
The platform exposes a few endpoints (OpenID, SAML2 and WS-Federation), but integrating these in your application isn't always a walk in the park. Especially when you want to mix this with other types of authentication, or if you're building a Single Page Application.
So in this article we'll look at how we can use Auth0 to do the heavy lifting and easily use the Belgian eID to authenticate in our AngularJS application.
Let's start.
Setting up Auth0
The first thing we'll do is add a new SAMLP Identity Provider under Connections > Enterprise. The Sign In URL should point to a SAML2 Browser Post endpoint (which can be found on the supported protocols page). The identification endpoint will simply read the user's card and the authentication endpoint will ask the user to enter his/her PIN code before the card can be accessed.
For this scenario we'll stick with the Identification endpoint: https://www.e-contract.be/eid-idp/protocol/saml2/post/ident. Now on that same page you can go ahead and download the certificate (identity.pem), which you'll get when clicking the "Identity certificate chain" link. Upload this certificate in the new connection you're creating.
One last thing you'll need to do is change the Request Template:
<samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="@@ID@@" AssertionConsumerServiceURL="http://localhost:62000/saml2/post" IssueInstant="@@IssueInstant@@" ProtocolBinding="@@ProtocolBinding@@" Version="2.0">
<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">@@Issuer@@</saml:Issuer>
</samlp:AuthnRequest>
On the third line you'll see that I added the AssertionConsumerServiceURL. The eID IdP needs this additional attribute since it will be using it as a Callback Url. Now because of how the eID IdP works this has to be a link pointing to your application. The eID IdP will match the HTTP referer of the original request with the AssertionConsumerServiceURL. If the hostname of both URLs don't match you'll get an exception.
We'll cover what you'll need to add in your application for this to work. The main idea is that our application receives the SamlResponse
and that we forward it to Auth0 where the authentication flow can continue (converting the SAML2 assertions to JWT, execute any custom rules, …). In my case I'm doing this redirect in an ASP.NET MVC 5 application, but this simple logic will also work in PHP, Java, NodeJS, …
Setting up the application.
Ok so the next step is to integrate this with our application. For this scenario we'll be integrating this in an AngularJS application so you'll need the auth0 module for AngularJS. In order to get this working you'll need to configure the your domain and client ID:
authProvider.init({
domain: 'sandrino.auth0.com',
clientID: 'wuY62uK3uGxR9b5TeRRWASP8iZ9tvVhY',
loginState: 'login'
});
And then simply add a button/link that will initiate the authentication flow. Since the eID IdP is not related to a specific email domain you won't be able to use the Auth0 Lock widget (this requires you to configure the connection with one or more domains after which you'll be able to enter your email address in the popup and get redirected to the right connection). That's why we'll manually choose the connection:
$scope.loginUsingEID = function () {
$scope.$parent.message = 'loading...';
$scope.loading = true;
auth.signin({
popup: true,
connection: 'SamlEid',
popupOptions: { width: 800, height: 450 }
},
onLoginSuccess, onLoginFailed);
};
And as a final step I'll need to configure the SamlResponse
redirect from my application to the Auth0 /login/callback endpoint. When we added the SAMLP Identity Provider we changed the Request Template with an AssertionConsumerServiceURL pointing to our application. My application is running on http://localhost:62000 and using ASP.NET MVC the path /saml2/post is mapped to my Saml2Controller
and the Post action in it. This controller simply takes the SamlResponse
it gets from the Identity Provider and renders it in a view.
Note that you'll also need to set the name of your Auth0 domain, we need this to know where to redirect the user after we get the SamlResponse
.
public class Saml2Controller : Controller
{
public ActionResult Post(string samlResponse)
{
return View("Post", new Saml2Response
{
Content = samlResponse, AccountName = "sandrino"
});
}
}
And finally we have the view which posts the SamlResponse to the /login/callback endpoint:
@model SampleApp.Models.Saml2Response
<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta http-equiv="Content-Script-Type" content="text/javascript" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta http-equiv="Expires" content="-1" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Accept-Charset" content="utf-8; q=0.8" />
<title>Redirecting...</title>
</head>
<body>
<div id="content">
<h2>Navigating back to web application...</h2>
<p>This page will automatically navigate you back to your web application.</p>
<form id="response-form" method="post" action="https://@(Model.AccountName).auth0.com/login/callback" accept-charset="UTF-8">
<input type="hidden" name="SAMLResponse" value="@Model.Content" />
<noscript>
<input type="submit" value="Submit" />
</noscript>
</form>
<script type="text/javascript">
document.getElementById('response-form').submit();
</script>
</div>
</body>
</html>
And we're done, Auth0 is taking care of the rest. Once the /login/callback
endpoint is ready auth0-angular will take over and we can simply use the profilePromise to get notified when the user has been authenticated:
myApp.controller('RootCtrl', function (auth, $scope) {
auth.profilePromise.then(function() {
$scope.$parent.message = 'Welcome ' + auth.profile.name + '!';
});
$scope.auth = auth;
});
To show the user's information I created a little view which shows the user's picture (yes, we also get the picture from the card in Base64) and the complete profile:
<div>
<br />
<h2>Your picture (be:fedict:eid:idp:photo)</h2>
<img src="data:image/jpeg;base64,{{ auth.profile['be:fedict:eid:idp:photo'] }}">
<h2>Your profile</h2>
<span>{{auth.profile | json}}</span>
</div>
Taking it for a spin…
Ok, let's see how this looks like. First we'll start the application and click the Login using your Belgian eID button:
auth0-angular will then take over and display a popup with the eID IdP:
And now it's time to insert my card:
The IdP will then read my card after which I'll be redirected to my application which will then post the SamlResponse the Auth0. After that my AngularJS application will consume the JWT and be able to access the full profile, including the user's picture:
The code for the AngularJS application with the ASP.NET MVC redirect logic is available on GitHub: https://github.com/sandrinodimattia/auth0-belgianeid-angularjs
Enjoy!