4

I'm trying to set up a single-sign-on service for a web page using the Azure Active Directory / OpenID Connect services from Microsoft.

I've got some of the way there, in that I can get their service to send me an id_token, but I'm struggling with how to authenticate/verify that token. As I received it from the users browser, rather than via a server-to-server request, I need to validate it, right?

To get the token, I just use a link:

https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize?client_id=[myclientid]&response_type=id_token&redirect_uri=https://localhost/ssotest.php&response_mode=form_post&scope=openid+profile&state=12345&nonce=678910

(For those reading trying to do the same, it took me ages to find, but you can set up your client id here: https://apps.dev.microsoft.com/)

That page then posts data to my script, which looks something like this:

array(3) {
  ["id_token"]=>
  string(1026) "abc.def.geh"
  ["state"]=>
  string(5) "12345"
  ["session_state"]=>
  string(36) "dd7781aa-74e8-4aa8-ac7e-d3800c5c2247"
}

From that point, I split up the ID token in to the header, body and signature, based on the periods/full-stops.

I can then base64decode the header:

["typ"]=> string(3) "JWT"
["alg"]=> string(5) "RS256"
["kid"]=> string(27) "MnC_VZcATfM5pOYiJHMba9goEKY" 

and the body:

["aud"]=> string(36) "[client_id]"
["iss"]=> string(75) "https://login.microsoftonline.com/52f161e7.../v2.0"
["iat"]=> int(1466523280)
["nbf"]=> int(1466523280)
["exp"]=> int(1466527180)
["ipaddr"]=> string(15) "111.111.111.111"
["name"]=> string(12) "Mr E Xample"
["nonce"]=> string(6) "678910"
["oid"]=> string(36) "c3beeb42..."
["preferred_username"]=> string(23) "email@example.co.uk"
["sub"]=> string(43) "oGAnGQ..."
["tid"]=> string(36) "52f161e7..."
["ver"]=> string(3) "2.0"

Now I have a signature, but I'm not really sure what to do with it. I understand I can get the right public certificate from https://login.microsoftonline.com/common/discovery/v2.0/keys as specified by the kid in the header, but I'm not sure how that helps. As I know the public key, I guess I need to decrypt the signature with it - is that right??

Surely there must be a way to send a server to server request to verify the information sent to me from the client? E.g. GET https://login.microsoftonline.com/verfifytoken/[token]

I set up Google SSO, which was a breeze compared to this - I'm sure I'm missing something, but it really does seem over complicated!

Any help would be very much appreciated - I've been reading the documentation for many hours now! I'd really like to avoid using libraries for this, if possible, so I can fully understand what is happening.

Ben
  • 4,707
  • 5
  • 34
  • 55
  • According to my experience, we can use [Authorization": id_token] into your header. And you can request your App URL(you register App using the URL ) with this header. – Will Shao - MSFT Jun 28 '16 at 06:08
  • Will, I think you've meant not "Authorization": id_token, but Authorization: Bearer [id_token]? – Konstantin Aug 24 '16 at 23:43
  • [this might help](https://stackoverflow.com/questions/43142716/how-to-verify-jwt-id-token-produced-by-ms-azure-ad) – spottedmahn Aug 10 '17 at 20:30

1 Answers1

0

As I know the public key, I guess I need to decrypt the signature with it - is that right??

Actually, what you need to do is verify the signature yourself.

The alg property tells you that the algorithm is RS256, which means RSA 256. I'm not a Python guy, but a quick search points me here (not sure if this library is the best...) where you can verify the signature. The message is the two first blocks of the JWT (as split by the '.'), and the signature is the third block.

Bruno Brant
  • 8,226
  • 7
  • 45
  • 90