Fimnet Login

Overview

Fimnet Login is a secure way for people to sign in to your site using their Fimnet account. It uses OAuth 2 and OpenID Connect. If you are new to OAuth and Open ID Connect, you can read more at  http://oauth.net  and  http://openid.net/connect .

If you are already familiar with OAuth, then all you need to know is the two authentication endpoints (authorization and token). They are:

Both testing and production is done on the same server https://auth.fimnet.fi.

Fimnet Login flow

The following schema shows the  Login flow. In green are the part you need to implement.

Before you begin to develop an application, you will need a client id and a client secret key. The client id and client secret key will be used to authenticate your application and verify that the API calls being are valid.

Upon successful authentication, you will receive an Access Token that gives access to  Fire API  and an ID Token containing the user identity, as defined by OpenID Connect specifications. You'll need to store the Access Token if you want to be able to make API calls on behalf on the user.

Login

1. Authorization request

To begin, you need to send the user to authorization endpoint.

https://auth.fimnet.fi/authorize
?client_id=[your_client_id]
&redirect_uri=[your_callback_url]
&state=[unique_value]
&response_type=code
&scope=openid
  • client_id should be set to your application’s client id.
  • response_type should always be set to “code”.
  • redirect_uri should be set to the URL that the user will be redirected back to after authentication. The redirect_uri must be the same as the one set in your client settings. You can add extra segments at the end, so for example, if your callback URL is "http://www.mysite.fi", then you will be able to use "http://www.mysite.fi/mypage" or "http://www.mysite.fi/?foo=bar", but not "http://www.myothersite.fi".
  • state is a anti-forgery token. You need to create a unique session identifier that holds state between your app and the user's client. It'll we passed back in the response, and you must make sure it's the same as the one you send to avoid Cross-Site Request Forgery attacks. One good choice for a state token is a string of random characters.

With FireAPIClient, you can generate the authorize URL easily and make a redirect:

$url = $api->getAuthorizeUrl(array(
 'redirect_uri' => $redirect_uri,
 'state' => $state
 ));  

2. Callback

Once the user has been authentified on Fimnet and has authorized your application to access his account, he will be redirected to the callback URL you provided in redirect_uri. The request will look like the following:

http://www.mysite.fi/callback?code=1e864386236c84bc4f7b5aad7c654858ffd7a7e3&state=[unique_value]

If the user denies the authentication, or if an error happens, the request will look like the following:

http://www.mysite.fi/callback?error=[error_code]&error_description=[error_description]

If everything goes well, first you must make sure that the value of state parameter is the same as the value you send in your authorization request.

Then you need to exchange the code for an Access Token and an ID Token. To do this, you will need to do a POST request to the token endpoint. The request will look like this:

POST /token HTTP/1.1
Host: auth.fimnet.fi
Content-Type: application/x-www-form-urlencoded
  
client_id=[your_client_id]
&redirect_uri=[your_callback_url]
&client_secret=[your_client_secret]
&code=[code]
&grant_type=authorization_code
  • You must pass your client id and client secret. They can also be passed as a HTTP Authorization header.
  • You must pass the exact same redirect_uri as you used in the authorization request.
  • grant_type is always "authorization_code".
  • code must be the code you received. The code is only valid for a very short time!

With FireAPIClient, the following code will take care of it:

$response = $api->getAccessToken(array(
 'code' => $code,
 'redirect_uri' => $redirect_uri
 ));

With cURL you can do the request with the following command (replace the values with your own info):

curl https://auth.fimnet.fi/token --data "client_id=mysite&client_secret=foobar&grant_type=authorization_code&redirect_uri=http://www.mysite.fi&code=1234"

If everything is fine, you'll receive a JSON object like this:

{
 "access_token": "17a18f538645da6f8f176dc2ab7859448f27d2d4"
 "expires_in": 86400,
 "type": "Bearer",
 "id_token": "a long string of encrypted data"
 }
  • access_token is a token for accessing Fire API on behalf of the user.
  • expires_in indicates the remaining time before the Fimnet Session is closed. Fimnet Sessions have a fixed duration, after which the user is automatically logged out. Your application should use this information to synchronise the user session with the Fimnet Session.
  • type is always "Bearer".

3. Obtaining user information from the ID Token

id_token is the OpenID Connect ID Token, a cryptographically signed JSON object encoded in url-safe base 64 (see Json Web Token). You must validate the token before you use it in your application. The validation consist of 2 steps: checking the cryptographic signature, and validating the token audience. We recommend that you use a library to do it for you. Our PHP class FireAPIClient will take care of validating and decrypting the ID Token for you.

If you want to check the signature manually, you need to split the token by ".". The third part is the signature and must be verified with our SSL public key. You can find the SSL public key in our php-client code on PHP Client -page. Example:

$separator = '.';
$array = explode($separator, $id_token);
if ( sizeof($array) != 3 ) {
  throw new Exception("Incorrect token format");
}

list($header, $payload, $signature) = explode($separator, $id_token);

// the signature uses a "url-safe" base64 encoding, so we need to do a bit of replacement to decode it
$decoded_signature = base64_decode(str_replace(array('-', '_'),array('+', '/'), $signature));

// The header and payload are signed together
$payload_to_verify = utf8_decode($header . $separator . $payload);

// $header = base64_decode($header);
$verified = openssl_verify($payload_to_verify, $decoded_signature, $public_key, defined('OPENSSL_ALGO_SHA256') ? OPENSSL_ALGO_SHA256 : 'sha256');

if ($verified !== 1) {
  throw new Exception("Invalid signature");
}

$id_token = json_decode(base64_decode($payload));

Once the ID token is verified and decrypted, it look's like this:

{"iss":"auth.fimnet.fi",
 "sub":"1234",
 "aud":"your_client_id",
 "iat":1353601026,
 "exp":1353604926,
 "auth_time": 135360100}

You must verify that iss is "auth.fimnet.fi" and aud is your client ID.

  • iat contains the timestamp at which the ID token has been issued (normally, the current server time).
  • exp contains the timestamp at which the ID token will expire. The ID token is valid for the remaining of the Fimnet Session, so in theory the value of "exp" is equal to "iat" + "expires_in", though due to the way the server works there can be a few seconds difference.
  • auth_time is the timestamp when the Fimnet Session started.
  • sub is the user's Fire ID. You will need it to query Fire API.

4. Authenticate the user

Now you have all the information you need to authenticate the user:

  • id_token.sub is the user's Fire ID
  • access_token will give you access to Fire API to fetch more info (such as name, Fimnet ID, etc.)
  • expires_in or id_token.exp indicates until when the session id valid.

Logout

Fimnet Login offers 3 behaviors for the logout.

The first and easiest is to log the user out of your application, but leave the Fimnet Session open. In this case, there is no interaction with Fimnet Login.

The second option is to log the user out of your application and then out of Fimnet. Just redirect the user to the end session endpoint:

https://auth.fimnet.fi/logout

The third option is to log the user out of Fimnet, and then out of your application. To do so, you need to redirect the user to the end session endpoint with an extra parameter "post_logout_redirect_uri". Example:

https://auth.fimnet.fi/logout?post_logout_redirect_uri=http://www.mysite.fi

With the PHP Client, you can do the following:

$api->getLogoutUrl();
$api->getLogoutUrl(array('post_logout_redirect_uri' => 'http://www.mysite.fi'));