Creating a responsive e-mail may give you strong headaches.
There are so many things to deal with! It is even more frustrating and time-consuming when you are stuck with a problem you are not able to solve, and finding the root cause can be a pain:

  • You have to deal with “bad practices”
  • Each e-mail client has its own CSS support
  • Some e-mail clients apply their own style
  • In some cases, e-mail clients modify the DOM of your e-mail
  • And many other atrocities that will make you have nightmares

This blog article aims to list the issues we encountered when creating our own responsive e-mails and give you leads to resolve similar issues.
I don’t claim to have THE solution, nor to be exhaustive. But I hope it will help.

The margin property doesn’t seem to work in Outlook.com

You might have noticed that your margins are ignored under Outlook.com. And you are right!
Outlook.com dropped the margin support as you can see in https://www.campaignmonitor.com/css/.
That is also the case for Office 365 (which is an Outlook.com you have to pay for).

Hopefully, there is a trick : Capitalize your margin property

Instead of writing margin: 10px;
Use Margin: 10px;

When I apply margin or padding on a table, Outlook 2007 and 2010 acts weird

When applying CSS margin or padding to a table, Outlook will apply the same margin or padding to every nested td.
Using these CSS properties on the containing table element should be avoided

The cellpadding and cellspacing properties are safe though.

Positioning with floats and positions does not work

As half of the most used e-mail clients dropped the CSS support of float and position, these two properties are to avoid in your developments.
Use HTML tables as workaround.

What is known as a bad practice in HTML development becomes a good one when it comes to e-mails.

Text and some elements look bigger in some e-mail client

Some e-mail clients apply their own style and can make your e-mails look a little bit different than what you expect
To avoid those unwanted behaviors, you should size every element with font-size, width or max-width.

Max-width does not work under Outlook

When you deal with responsive e-mails, you certainly use the max-width property to limit the width of fluid elements on larger screens.
And this is definitely a good practice… Which doesn’t work in Outlook, as it has dropped the support for this CSS property.
It means that, in Outlook, an element with a max-width property will take all the available place.

The trick here is to wrap all your fluid elements into a container with fix size, in a HTML conditional comment that targets Outlook.

<!--[if (gte mso 9)|(IE)]>
    <table width="430" align="center" border="0" cellpadding="0" cellspacing="0">
        <tr>
            <td>
<![endif]-->
<table align="center" border="0" cellpadding="0" cellspacing="0" style="max-width: 430px;">
    <tr>
        <td>
            [Content goes here]
        </td>
    </tr>
</table>
<!--[if (gte mso 9)|(IE)]>
            </td>
        </tr>
    </table>
<![endif]-->

This conditional expression targets all Microsoft Outlook (mso) versions greater than or equal to version 9 as well as Outlook versions that use Internet Explorer to render (like Outlook 2000–2003) and Lotus Notes.

Table are not centered in Gmail (Safari)

If you try to center a table with the align="center" attribute, you may have noticed that the display is not the expected one in Gmail when you open it from Safari.
For some obscure reasons, it just ignores it and the table is not centered.

The trick is to simply center the table with the CSS Margin property.

Responsiveness is broken in Gmail in discussion mode

You may have noticed that Gmail detects the duplicate contents between the mail of a same conversation.
It highlights these contents by coloring them.

To apply this new style, Gmail changes the DOM of your e-mail by wrapping the duplicate contents into a div with a specific style.
This wrapper is obviously not responsive and breaks the responsiveness of your e-mail.

As the grouping by conversation depends on the recipient configuration, there’s nothing you can do to avoid this unwanted behavior.
The solution is to be careful when making your campaign.
If you send several similar e-mails to the same recipient, then you must change the subject of your e-mail.

There’re unwanted gaps around images in table cells

Randomly, you can see a gap above and/or below your images in <td>. It’s often a discrete gap of 1px that shows depending on the e-mail client or the screen resolution.
Most of the time, you won’t even notice it unless:

  • You have a background color under your image that is different from the other parts of the e-mail
  • You want to put images side by side in two differents table cells

How to remove the gaps

To remove those gaps, you have to apply this style to your image:

.img {
    display: block; /* Causes a line break before and after your image */
    border: none; /* Lotus Notes sometimes add borders around images */
    width: [feel free to choose the good one];
    height: auto; /* In rare occasions you'll still have a small gap. Use height: 100% in this case. Caution: it can change the image's ratio */
}

The display: block; trick is the most popular one when it comes to images. But if it is not enough, you should take a look at this page.

The bottom gap in Outlook.com

Even with the previous trick, you won’t prevent the gap in Outlook.com.
The root cause is because Oulook.com (and Office 365) wraps images in a HTML button. This causes a huge gap of 5px at the bottom of every image of your e-mail, and there’s nothing you can do to prevent this behavior.

The only workaround is to wrap all your images in a div with the wanted height. Fortunately, fixing the height will not break the responsiveness!

In the CSS1 specification, browsers can only display fonts that are present on the user’s system. This is the reason why the font-family attribute accepts a list of fallback fonts in case the first font is not recognized.

In 1996, Microsoft delivered for free a pack of fonts: Core fonts for the Web. They are now outdated, but you surely know some of them:

  • Arial
  • Comic Sans
  • Courier New
  • Times New Roman
  • Verdana

There also exists five categories of fonts that are often used as fallback fonts:

  • sans-serif
  • serif
  • monospace
  • cursive
  • fantasy

CSS2 specification has given birth to a new property: @font-face.

This property allows you to use new fonts, compatible with all current browsers, thanks to the management of various formats:


Name Format Details Support
Embedded OpenType fonts EOT Supported only by Internet Explorer 4.47%1
Scalable Vector Graphics fonts SVG Deprecated, supported only by Safari 28.35%1
TrueType and OpenType fonts TTF and OTF Old formats supported by almost all browsers (except IE) 94.53%1
Web Open Font Format WOFF Most recent format, recommended to use (the equivalent of TTF/OTF, but compressed) 93.76%1
Web Open Font Format 2 WOFF2 New format, not yet supported by all browsers (better compression) 74.49%1

Since 2010, Google has given access to a great number of free and open source fonts that are very easy to integrate to any website: https://fonts.google.com/.

Example

Let’s imagine I have created or downloaded a font called WebFont, and I want to use it by default for all the texts used on my website:

@font-face {
  font-family: 'WebFont';
  src: url('/fonts/webfont.eot'); /* IE9 Compat Modes */
  src: url('/fonts/webfont.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
       url('/fonts/webfont.woff2') format('woff2'), /* Super Modern Browsers */
       url('/fonts/webfont.woff') format('woff'), /* Pretty Modern Browsers */
       url('/fonts/webfont.ttf') format('truetype'), /* Safari, Android, iOS */
       url('/fonts/webfont.svg') format('svg'); /* Legacy iOS */
  font-weight: normal;
  font-style: normal;
}

body {
  /* If my browser does not find or cannot read my font,
     it will automatically fallback on the sans-serif category */
  font-family: 'WebFont', sans-serif;
}

If the font exists in different variations (bold, italic, etc.), it is possible to declare them all under the same name. This will allow to automatically apply a style to all elements with the type bold (strong, b) and/or italic (em, i):

@font-face {
  font-family: 'WebFont'; /* Make sure to keep the same name here! */
  src: url('/fonts/webfont-bold.eot');
  src: ...; /* State all formats here */
  font-weight: bold;
  font-style: normal;
}

@font-face {
  font-family: 'WebFont'; /* Make sure to keep the same name here! */
  src: url('/fonts/webfont-italic.eot');
  src: ...; /* State all formats here */
  font-weight: normal;
  font-style: italic;
}

@font-face {
  font-family: 'WebFont'; /* Make sure to keep the same name here! */
  src: url('/fonts/webfont-bold-italic.eot');
  src: ...; /* State all formats here */
  font-weight: bold;
  font-style: italic;
}
<p>Text using the default font.</p>
<p><strong>Text using the bold font.</strong></p>
<p><em>Text using the italic font.</em></p>
<p><strong><em>Text using the bold italic font.</em></strong></p>
<p><em><strong>Text using the bold italic font.</strong></em></p>

It is of course possible to define utility classes in order to apply the bold and/or italic style to any element:

.bold {
  font-weight: bold;
}

.italic {
  font-style: italic;
}
<p class="bold">Text using the bold font.</p>
<p class="italic">Text using the italic font.</p>
<p class="bold italic">Text using the bold italic font.</p>

  1. Global support at the time this post was written.  2 3 4 5

Most of you have heard about SSO and maybe SAML. But it’s always an obscure part of authentication system in people’s minds. Here is some basic explanation about SAML, I will not enter in details about security and all the data sent from a platform to another. The aim is not to be too much technical to understand the connection process. The first thing to know is what a SSO is, and what is the purpose.

1 - What is a SSO?

SSO is the name of an authentication process. An SSO (Single Sign-On) allows a person to connect to multiple applications without entering his password each time. One access control is enough. The opposite process is SLO (Single LogOut).

SSO example

Benefits are:

  • One password to remember.
  • Less prompts, so less time spent typing his password.
  • Help desk costs lowered.

Problems are:

  • Security must be enforced.
  • If the authentication server is down, all these applications are not accessible anymore.
  • Need a good identity data governance.

Here is an example of a Facebook SSO in the Spotify login page.

spotify sign in with facebook

The behaviour here is, if you have an account on Facebook and you are already logged in, once you click on the “Sign up with Facebook” button, Facebook will give some of your data to Spotify to create an account (if you don’t have one yet) or will retrieve your existing account. If you are not already logged into Facebook, the website will ask you for your Facebook credentials before accessing the music platform.

2 - How SAML works

a- Overview

SAML stands for Security Assertion Markup Language and the most common version is SAML 2.0, the latest version. This protocol is based on XML exchange and enables web-based authentication and authorization scenarios. The exchange is made between an Identity Provider (IDP) and a Service Provider (SP). The role of the IDP is to confirm if the user can loggin or not. The SP sends a request to the IDP to know if the user can log in and the IDP grants access if the login is validated. In the example above, Facebook stands for the IDP and Spotify the SP. The internet browser is the bridge between the IDP and the SP because they both communicate with HTTP requests made in GET, POST or Artifact.

b- Technical details

Setup

A SAML connection has to be configured : the IDP must store the connection urls and the security key of the SP, and vice-versa. These informations are referred to as the IDP and SP metadata, they ensure a secure transaction between the IDP and a SP. The security key is a public key that will be used to encrypt the message. To simplify and understand what encryption is, in the movie “the imitation game” Alan Turing and Christopher Morcom were chatting in class with encrypted messages written on papers that no one could read without knowing the encryption code, to avoid being caught by the teacher. Once the public keys are shared, all communications will be encrypted with the keys.

Once both sides are configured the authentication is possible.

The connection sequence

The scenario is: the user wants to connect to his eLearning platform through his company intranet. Both are SP. The IDP is just a server that contains all the company accounts.

What the user sees

1 - The user access his intranet, but he is not connected, he clicks on the “Connect to intranet button”.

authentication step1

2 - He is redirected to the company authentication server (IDP), where he is not connected. He fills the credentials and clicks on login. He is now connected to this server and get redirected to the intranet site.

authentication step2

3 - Now the user is on his company intranet with his account. He can access all the content of the intranet and he wants to do his eLearning content. He clicks on the button to access the eLearning platform.

authentication step3

4 - The user is redirect to the eLearning platform with the same account has the one on the intranet.

authentication step4

What really happens

  • The SSO request: When the user clicks on the login button of the intranet, the intranet will send an AuthnRequest to the company authentication server (IDP). An AuthnRequest is a request sent from the SP to the IDP to ask if the user can connect (image 1).
  • The SSO authorization: The IDP will analyse the AuthnRequest (does he know the intranet, are the certificates correct, etc). If everything is correct, the IDP will check if the user is already logged in (with cookies for example). In our scenario it’s the first connection of the user to a company platform so he is not connected for now. Therefor IDP displays a login/password page (image 2). Once the credentials are validated, the employee is connected on the IDP and this one will send a Response to the SP. The Response is a message from the IDP to the SP that contains the user data (ex lastname, firstname, employee id, etc) and a status (access granted or not). Once the access is granted he will be redirected to the intranet homepage (image 3).
  • The SSO in action: The user clicks on a link in his intranet that redirects him on the company eLearning platform. During the page loading, the eLearning platform will send to the IDP an AuthnRequest. The IDP then replies with a Response that grants access to the eLearning platform. The employee is now connected on the eLearning platform with his account (image 3). He will never see the eLearning platform login page because he is already connected on the IDP.

Messages between SP and IDP, such as the AuthnRequest and the Response, are called Assertions.

3 - Why use SAML over other protocols?

SAML 2.0 is mostly used in B2B because of the Active Directory Federation Services (ADFS) that is a component of Windows Server. This allow to plug the company ‘s Active Directory (AD) with all the applications you want. Lots of companies use the AD to manage employees account. If an employee is not present in the AD, he will not be able to connect any company application. The IT team have to manage only one database for all employees. Futhermore SAML 2.0 and ADFS are easy to install and configure, SP and IDP communicate through HTTP requests, no need to open ports in firewalls.

In this example with Facebook and Spotify, the protocol used is OAuth (protocol used by Facebook, Gmail, Yammer to communicate with other applications), not SAML. OAuth is a most recent protocol that’s why this protocol is not very common in companies and mostly used in B2C businesses.

4 - TL;DR

SAML is just the way authentication and authorization are transmitted between an IDP and an SP. The SP asks for an authorization (AuthnRequest), the IDP checks if the request is valid, checks if the user exists and is authorized to access the SP application and sends its response (Response). Those messages are called Assertions. If the access is granted, the user will be connected on the SP with his account, otherwise the connection will be denied. The company manages only one database with authorized accounts. SAML communication transits with HTTP requests that allows to deploy SAML without modifying the company firewall.

Welcome! You’re here because you’re curious about Oauth2 and wonder what the heck it is? You are in the right place, young dummie. Go ahead ask your question!

* What’s Oauth2 in three words??*

An authorization protocol.

And with a few more words?

Basically, it’s a protocole that defines a way for an application to get an authorization to request an API in the name of a user. The authorization is materialized by a token which can be acquired in four different ways, depending on the server which proposes it. There you go, you know everything, thank you for your attention! Ok just kiddin’. Let’s get started!

Development: Oauth2 genesis

A word about Oauth2 history: It was written to improve Oauth1 complexity, in a good way, though some would say at the expense of security… The workflow is similar, but there are less parameters and configuration to do.

I’ve never cared much for History anyway, I’m more curious ‘bout how it works and how to implement it!

Neither did I so let’s get started, for real this time.

Cast

Let’s talk about the actors and their roles. Even the extras.

What?! All at once?!!!!!

Yeah, all at once, cause it’s the best way to understand it.

Let’s say you have a website which needs some information about the Google account of its users. It can be for authentication, but it might also want to access info like the Youtube channels the user is following. (here is the list of all those Google APis that are available: https://developers.google.com/apis-explorer/#p/). Google allows you to do just that by following the Oauth2 protocole.

That’s for the synopsis and the actors. Now about the official roles as defined in the protocol:

  • The information you need are called the resources.
  • Your website, the one which needs information on the user by Google, is called the client.
  • Your user is called the ressource owner. Logic, it’s his information!
  • Google, or any other Oauth2 server, is the resources server. That’s were are stored the information.

Got it! Now how does it work?

Not so fast young Padawan. As I said in introduction, the authorization is matherialized by a token. Before requesting the ressource server, you will need to get one. That’s when the guest star makes its unexpected apparition!

Who’s that? o_O

  • Well it’s an entity which will be called the authorization server, and which is divided in two sub entities: the authorization endpoint, and the token endpoint.

Don’t worry for now they’re wearing a mask, but you’ll see their faces and understand what they are exactly in the following.

Plot (Authorization Grant Code Version)

This is one of the four ways to get the token I talked about earlier, it might be the most complex, but above all it’s the most used, and the most complete and secure!

Pre-production: the Client Registration

First and before everything, the client has to be registered to the authorization server. It’s done backstage, before the user enters on the scene. During this registration, the client will be given a client Id and a client Secret while giving the authorization server a redirect Url.

What are they? Oh god, this movie is gettin’ complicated. -_-

Come on we’re almost there, they are merely part of the movie set! The client Id and the client secret are confidential string identifiers for the client to use. The redirect Url, you’ll see quite soon.

Diagram Workflow

Quickly, when the user will browse the Client and this one will need resources from the resource server, it will redirect the user to the Authorization endPoint on which the user will authenticate and grant rights to his resources to the Client. He will be redirected by the Authorization to the Client with a code which the Client will use to request (using curl for example) a token to the Token Endpoint. With this token, the Client can request the Resource Server Api. The End!

And I did it without catching my breath! But let’s take a look to the diagram, u’ll undestand everything:

Ressource Owner (RO/User)->Client:browse Note right of Client:Client needs resources Ressource Owner (RO/User)->Authorization EndPoint:is redirected by Client (1) Ressource Owner (RO/User)->Authorization EndPoint:authenticates and agrees the Client to access his ressources(2) Authorization EndPoint->Client:redirects RO to Client with a code as parameter(3) Client-->Token EndPoint:uses the code to request token(4) Token EndPoint-->Client:returns a token(5) Client-->Resource Endpoint:request resources as many times as it needs, as long as the token is valid(6) Resource Endpoint-->Client:returns resources(7)

(1) Client redirects the Resource Owner with the following GET Parameters:

  • response_type (r) = code (for the authorization code grant it’s always that)
  • client_id (r) = the one given to Client by the Authorization server at registration
  • redirect_url (r) = the redirection url entered by Client on the registration to Authorization server
  • scope (o) = a new part of the movie set! It is the set of rights the Client wants to be granted by the Ressource Owner. It’s optional, not all Oauth2 server require some (Facebook for example doesn’t)
  • state (o) = it’s like a CSRF token that the client will generate. The authorization Endpoint won’t make anything of it, it will just give it back untouched in (3)

(r) = required (o) = optional

(2) Ressources Owner identifies himself on the Authorization Server and grants the rights to the Client:

If the RO is already loggued in on the Authorization Platform (for example, he has already opened his Gmail Inbox), he will only be asked to grant the rights When the RO has granted the rights once, this grant is stored and he won’t be asked again. As a result of those two postulats, if the user is already loggued in and has already granted the rights (at a previous browsing on the Client for example), this step is ignored.

(3) Authorization EndPoint redirects Resource Owner to Client the following GET parameters:

  • code (r) = a code that the Client will use to request a token
  • state (o) = the state potentially previously given by the Client to the Authorization Server during (1). The client may use it to make sure the redirection is from the AS.

(4)(5) Client uses the code to request the token to the Token EndPoint

Here it’s not a redirection. The Client server uses a cUrl (or equivalent). The GET parameters are the following:

  • code (r) = the code handed to the Client by the Authorization Server
  • grant_type (r) = authorization_code (for the authorization code grant it’s always that)
  • client_id (r) = the one given to Client by the Authorization server at registration
  • client_secret (r) = the one given to Client by the Authorization server at registration If the parameters are recognized by the Token EndPoint, it will sent back the token, most of the time as a json (then again it’s not normalized by the protocol, for exemple Facebook gives a query string, and neither is the format of the resulting array, levels and indexes).

This last step is not part of the protocole per say. The protocole stops when the token is issued. Actually not really, but we’ll get into that later.

Oh my god, another twist, I want my mummy! T_T

Don’t be a baby! Keep going!

(6)(7) Client uses the token to request resources to the Resource Server

Here it’s not a redirection either. The Client server uses a cUrl (or equivalent) to request the resources to the Resource Server. Beware: the use of the token is not part of the protocole, so the Ressource Server might accept it as an Authorization header or GEt parameter with the name of its fantasy…

Ok you’re all set. The End!

** Wait no! You said there was a twist, that this didn’t cover it all! **

I know, this movie is endless…

Rewind with the refresh token

There’s something you haven’t asked.

What’s your favorite actor or movie?

No -_-.

The lifetime of tokens! Indeed, tokens are not immortal, they expires.

Oh… So when it happens, the client has to do it all over again?

It depends, sometimes yes. But as I said previously, once the user has granted the client the rights to access his ressources and if he still loggued in the Oauth2 server, the redirection is completly transparent for him he will just see a fast reload of the page (depending on you client code efficiency for whatever it does of course). Then the request to the token server to server (Client to Token Endpoint) and BOOM, the client gets a new token.

Sometimes? But other times?

Sometimes the Token Endpoint will issue with the access token what’s called a refresh token. This token will survive the former and can be used to get a new access token directly with the Token Endpoint. You don’t have to go throught the process with the Authorization Endpoint to get a code, the refresh token is the code in this exchange.

Authorization EndPoint->Client:code to request token Client-->Token EndPoint:uses the code and grant_type=code Token EndPoint-->Client:returns the access token and refresh token Note right of Client: access token expires Client-->Token EndPoint:uses the refresh token and grant_type=refresh_token Token EndPoint-->Client:returns the access token and refresh token

Alternative ends: the other Oauth2 workflows

The basis of Oauth2 is the token to request an API. We’ve just seen the most common worflow, the Authorization Code Grant. Three others types exist:

The Implicit Grant workflow: Basically it looks like this: response_type = token

Ressource Owner (RO/User)->Client:browse Note right of Client:Client needs resources Ressource Owner (RO/User)->Authorization EndPoint:is redirected by Client with response_type=token Ressource Owner (RO/User)->Authorization EndPoint:authenticates and agrees the Client to access his ressources Authorization EndPoint->Client:redirects RO to Client with the token as parameter(3) Client-->Resource Endpoint:request resources as many times as it needs, as long as the token is valid Resource Endpoint-->Client:returns resources

Here the client is a Javascript one, meaning that the request to Resource Endpoint are done on the user side, with an Access-Control-Allow-Origin header. The Client gets the access token in one call, but it transists throught client side which makes it the least secure.

The RO Credentials Grant workflow: Here it can be confusing. Basically, the Client will ask the Resource Owner for his credential on the Oauth2 server and send them directly to the Authorization Server which will return the token. Obviously, there has to be complete trust between Client and Authorization Server, they have to be part of the same “entity” since the former will have the credential of the RO on the latter. For example we can imagine that the login page domain of Google is the only one to be able to do this with the Google Authorization server. response_type = password

Ressource Owner (RO/User)->Client:authenticate with login and password Client->Authorization Server:requests Access token with login and password Authorization Server->Client:returns access token, refresh token(o) Client-->Resource Endpoint:request resources as many times as it needs, as long as the token is valid Resource Endpoint-->Client:returns resources

The Client Credentials Grant workflow: When the client is the ressource Owner… Its credentials are the client_id and client_secret and it will send them directly to get directly an access token. response_type = client_credentials

Client->Authorization Server:requests Access token with its client_id and client_secret Authorization Server->Client:returns access token, refresh token(o) Client-->Resource Endpoint:request resources as many times as it needs, as long as the token is valid Resource Endpoint-->Client:returns resources

Trailer: example of code in PHP

Here is your page oauth2.php which is accessed via the url OAUTH2_CLIENT_URL. It will be the page which will first redirect the user, then be the redirect url which will require the token and store it. OAUTH2_AUTHORIZATION_URL is the Authorization Endpoint Url. TOKEN_ENDPOINT_URL is the Token Endpoint Url. Let’s imagine you have a class Oauth2TokenManager which has the following method:

  • getAccessToken(): check that it has a token stored in session, return it if so, false otherwise.
  • requestAccessToken($code,$tokenEndPoint): makes the curl to the TokenEndPoint to get the token with the code and returns the returned access Token.
  • storeAccessToken($accessToken): stores the access Token in Session

oauth2.php

 <?php

$tokenManager = new Oauth2TokenManager();
$token = $tokenManager->getAccessToken();
/* if no token, either we haven't requested the code to the Authorization Endpoint Yet, or we have just been redirected from it (it is a redirection from AE and there is an error, drop it or try again by redirect to self with no $_GET parameters)*/
if (!$token &&!isset($_GET['error']))
{
    /* if not error in $_GET, if it's not a redirection from AE , there is no code in $_GET  so let's redirect now */
    if (!isset($_GET['code']))
    {
        $authorizationEndPointRedirect=**OAUTH2_AUTHORIZATION_URL**;
        $parameters = 'response_type=code
        &client_id='.**CLIENT_ID**.
        '&redirect_uri='.**OAUTH2_CLIENT_URL**;
        // redirect to AE with the right parameters which will redirect back to here 
        header("location:".$authorizationEndPointRedirect."?".$parameters);
        exit;
    }/* otherwise it's a redirection from the AE with the code!*/
    else
    {
    // makes the curl to Token Endpoint with the code given as $_GET
    $access_token = $tokenManager->requestAccessToken($_GET['code'],**TOKEN_ENDPOINT_URL**);
    // store the token
     $tokenManager->storeAccessToken($access_token);
    }
    // from now there should be a token 
    $token = $tokenManager->getAccessToken();
}
else if (isset($_GET['error']))
{
//Treat by redirecting again without $_GET or do whatever you want
}

// At this point $token exists and is ready to request the API, enjoy!!!

A word about security

Quick word about security: there are some security issues with Oauth2 which you are advised to look into before implementing your Oauth2 Client / Server. Google is your friend to look into this as I am too tired (and not actually adequate) to talk about it.


Here you go, hope you have a better understanding of Oauth2 after that.

The End

One of the most important constraints to migrate from a version control software to another is to keep all the branches and the development history intact. In many projects people choose the easy way by initiating a new project based on the last master branch. However, by doing so, they will end up losing all of that project’s history.

In this article I will explain how to use hg-git to convert a hg repository to git and keep all the history, branches, commits, etc.

First you should clone the hg-git repository

$ hg clone git://github.com/schacon/hg-git.git

To Enable the extension we should add the following section in ~/.hgrc file

[extensions]
hggit = [path-to]/hg-git/hggit

If you try to clone a mercurial repository which contains a git repository you will get an error, so to avoid this you should add the following configuration to ~/.hgrc file

[git]
blockdotgit = false

Each hg bookmark will be converted by hg-git to a git branch. So if you want to convert all the hg branches you should bookmark them all by using this script

#!/bin/bash -x

for hgrevision in $(hg branches | grep -v 'inactive' | rev | cut -d' ' -f 1 | rev)
do
   userevision=$(echo $hgrevision|cut -d ':' -f 2)
   hgbranchname=$(hg log -r $hgrevision | grep 'branch:' | cut -d ':' -f 2- | cut -b 7- | sed 's/[^a-zA-Z0-9]/ /g' | tr ' ' '_')
   hg bookmark -r $userevision "$hgbranchname"
done

Once the hg-git is configured you should initiate a new git repository using this command

git init

And in the hg repository folder we should execute this command to run the conversion

hg push /path-to-git-rep

Finally if your hg repository contains a git repository we should clean the new converted one to delete all the .git folders from the history using the bfg repo-cleaner. So you should download the tool from this url https://rtyley.github.io/bfg-repo-cleaner/ and run the following command

$ java -jar bfg.jar --delete-folders .git --delete-files .git --no-blob-protection my-repo.git

After this you can push the new repository to the remote server and check that all the branches have been converted.