Download as pdf or txt
Download as pdf or txt
You are on page 1of 6

Enable Persistent Login

This document explains how to decrypt the FB News Token to enable persistent login for your subscribers
who have linked their Facebook account to their subscription account.

The FB News Token is an encrypted token appended to the referral URL of a link on Facebook. In other
words, when a user clicks on a link from your publication on FB, the token is attached to the end of that
URL. This is what enables a true persistent login experience for your readers that have chosen to ​link their
FB profile to their subscription​ with you.

When you ​onboard to the API​, you will be eligible to receive the FB News Token automatically. Contained
in the payload of the token is a unique identifier which you can use to identify the subscriber coming to your
website from Facebook, and then auto-authenticate them. This unique ID is the same string of characters
you pass to FB via the API via the ‘​login_token​ ’ parameter.

The news token is a two-segment string separated by a ‘​.​’ where the first segment contains a 
Base64-encoded initialization vector and the second segment contains a Base64-encoded encrypted 
payload. The encryption algorithm used is AES 256 with Cipher Block Chaining (CBC). 
InitVector​ .E
​ncryptedPayload 
 
each token will contain an expiration time, which is set to 30 minutes after token generation. This is intended 
to help prevent access abuse.  

Before You Start

You will need:

● The subscriber must have​ linked their Facebook and subscription accounts
● The unique ​`login_token` of the subscriber
● The a​ pp secret of your Facebook app​. In order to decrypt the token, you will need a 256 bit key that is 
unique to your publication. 
● FB will only insert the FB News Token in URLs that are using HTTPS. Publishers must reject tokens 
received over HTTP. 

Decrypt the FB News Token


Use one of the following code samples to decrypt the FB News Token of a referral url that has come from
Facebook.

PHP 
list​
($
​encoded_init_vector​
, $
​encoded_encrypted_payload​
) = 
e
​xplode​
('
​.'​
, ​
$token​
); 
$init_vector​= ​
base64_decode​
($
​encoded_init_vector​
, t
​rue​
); 
$encrypted_payload​= b
​ase64_decode​
(​
$encoded_encrypted_payload​
, ​
true​
); 
 
$decrypted_payload​= o
​penssl_decrypt​

$
​encrypted_payload​

'
​aes-256-cbc'​

'
​my_encryption_key'​

OPENSSL_RAW_DATA, 
$
​init_vector​

); 

C#
using​​System​

using​​System​
.S
​ecurity​ .C
​ryptography​; 
using​​System​
.T
​ext​ ; 
using​​System​
.I
​O​; 
... 
string​[] ​
tokenElements​= ​ token​
.S
​plit​ (​
'.'​
); 
byte​[] ​
initVector​= C ​onvert​
.F
​romBase64String​ (t
​okenElements​
[0
​​
]); 
byte​[] ​
encryptedPayload​= ​ Convert​.​
FromBase64String​ (​
tokenElements​[​
1]
​); 
 
string​​decryptedPayload​= ​ null​
;  
using​(​
AesManaged​​ aes​= n​ew​A
​esManaged​ ()) 
{   
I
​CryptoTransform​d ​ecryptor​= a
​es​.​
CreateDecryptor​ ( 

Encoding​
.A
​SCII​ .G​etBytes​
(e
​ncryptionKey​ ), 

initVector​); 
 
u
​sing​ (M​emoryStream​m​s​= ​
new​M
​emoryStream​
(e
​ncryptedPayload​
)) 


using​ (C​ryptoStream​c
​s​= n
​ew​C
​ryptoStream​

ms​, 

decryptor​ , C
​ryptoStreamMode​
.​
Read​
)) 


using​ (​
StreamReader​r
​eader​= n
​ew​​
StreamReader​
(​
cs​
)) 


decryptedPayload​= r​eader​
.​
ReadToEnd​
();  


}  

 
Node.js 
const​​
crypto​= ​
require​
('
​crypto'​
); 
/* Do not run this code on the client side, as it WILL expose your encryption key */ 
function​​
decryptFacebookLoginToken​
(​
loginToken​
, ​
encryptionKey​
) { 
const​​
tokenElements​= l
​oginToken​
.​
split​
(​
'.'​
); 
const​​
initVectorBase64​= ​
tokenElements​
[​
0​
]; 
const​​
encryptedPayloadBase64​= t
​okenElements​
[1
​​
]; 
const​​
initVectorBuffer​= ​
Buffer​
.f
​rom​
(​
initVectorBase64​
, '
​base64'​
); 
let​​
decipher​

try​{ 
/
​/ Init Vector could have the wrong length 
d
​ecipher​= ​
crypto​
.c
​reateDecipheriv​
(​
'aes-256-cbc'​
, e
​ncryptionKey​
, i
​nitVectorBuffer​
); 
} c
​atch​(​
e)
​ { 
r
​eturn​​
null​


const​​
encryptedPayload​= ​
Buffer​
.f
​rom​
(​
encryptedPayloadBase64​
).​
toString​
(); 
let​​
initialBuffer​

try​{ 
i
​nitialBuffer​= ​
decipher​
.u
​pdate​
(​
encryptedPayload​
, '
​base64'​
); 
} c
​atch​(​
e)
​ { 
r
​eturn​​
null​


let​​
finalBuffer​

try​{ 
/
​/ Due to URL encoding issues this call may fail claiming invalid length 
f
​inalBuffer​= ​
decipher​
.f
​inal​
(); 
} c
​atch​(​
e)
​ { 
r
​eturn​​
null​


const​​
decryptedBuffer​= ​
Buffer​
.c
​oncat​
([​
initialBuffer​
, ​
finalBuffer​
]); 
const​​
decryptedPayload​= ​
decryptedBuffer​
.t
​oString​
(); 
let​​
decryptedObj​

try​{ 
/
​/ Ensure decrypted payload is valid JSON 
d
​ecryptedObj​= ​
JSON​
.p
​arse​
(d
​ecryptedPayload​
); 
} c
​atch​(​
e)
​ { 
c
​onsole​
.e
​rror​
(e
​​
); 
r
​eturn​​
null​


return​​
decryptedObj​


Example Facebook Referral URL
https://www.fbsampledomain.com/article1.html?fb_news_token=uu0yIwgT3tGhY6X1b3u0
LQ%3D%3D.lmkZ%2BsSNFKlSPcHYIZh6HxeA6OwesDbtW9oTf6Jqws3UP%2FDH3qnGPX22RXHPto%2BH
cYhUUdXHt9wdfAsHX4R7zkvAIIFX3AICpY0YV80UedsPiHx9lnAzLmE8b18JM2LizJj%2FAvN953Qh%
2B5li1KNnvDbgEwyQYWytSZBUwXfs1AwgtdN%2BdSRNNuWfyNDWDad6PHIduQ%2Bf%2FrcFOQl8Qwuo
QUh4lRWlO%2FfEF3ExkrBx4TzmeqA1BdZplfAn7AWFjLshO9SnkSDuEdomWp86d5kmVUsLvbLTuNM8E
EdYeQNFQ24%3D

Example Decrypted Payload


"Tid":​
"fb_5ec43a6aac5d93745609380"​ , 
"iss":"https://​ www.facebook.com​
", 
"Iat":​
1589918308​ , 
"exp":​
1589920108​ , 
"url":​
"https://www.fbsampledomain.com/article1.html"​

"bypass":​
true​, 
"is_subscriber":​ true​, 
"sub_id":​
"subid123" 

Parameter descriptions  
Label Description

tid  Unique identifier for the token.

iss  Issuer of the token

iat  Unix timestamp of token creation

exp  Unix timestamp of token expiration time

url  The canonical URL of the article carrying the token

bypass  This is a binary value that indicates whether a subscriber should be granted
access (‘true’ or ‘false’)

is_subscriber  A binary value that will render as ‘yes’ for linked subscribers, and ‘no’ is there
is no subscription link.

sub_id  The unique subscriber_ID passed to FB via the API as the “login_token”
 

Best Practices
Upon token receipt, publisher must:
● Reject any token received over HTTP
● Decrypt the token payload using the app secret as the crypto key.
● Validate the expiration date. Within the payload of the token, FB will list the expiration date and time
of the token. Ensure the session is occurring within this timeframe.
● Validate the URL. The URL requested of the publisher needs to match the canonical URL contained
within the payload. Each token is unique to each article. This is an abuse prevention measure.

You might also like