somtoday-api-docs icon indicating copy to clipboard operation
somtoday-api-docs copied to clipboard

SSO Authentication flow

Open elisaado opened this issue 5 years ago • 78 comments

SOMToday has introduced a new way of authentication, and there are already several organisations that have enabled it and disabled username/password authentication. I found this out when #6 was opened.

I am afraid that it is not possible to retrieve tokens this way but I hope that there is still hope for us.

What I need:

  • Either someone to provide me with a school, username and password of an account that can use SSO. (I understand that this is very sketchy) I will use them to analyse the requests made by the SOMToday app via a proxy, and will add the requests to this documentation.
  • Or someone to provide me with the requests made by the app when using SSO.

I have created a gitter room for further informal discussion: https://gitter.im/somtoday-api-docs/community

elisaado avatar Jun 07 '20 13:06 elisaado

I have recently tried to use a proxy to analyse the data requests made. However the SOMToday app and website, at least on iOS, do not allow custom certificates, which makes it impossible to see all of the networks requests and responses.

Do you know a quick fix that might be of help?

ChielChiel avatar Jun 10 '20 18:06 ChielChiel

Yeah the app uses certificate pinning, I know how this can be bypassed on android but not on iOS, the search term you need on Google is "disable certificate pinning iOS".

Thanks for wanting to help though :)

elisaado avatar Jun 10 '20 18:06 elisaado

How would the refresh token look like? Because it might be that the SSO login just returns a refresh token, from which the somtoday fetches the acces token for example. Or is that a crazy thought? Because today I came this far in intercepting the network requests made in the login process:

After login, the login.microsoftonline.com does the following get request:

GET https://somtoday.nl/oidc?code=0.ASEAv2TsGHBKb0OpDES5ibWnWpu4KK264sBLou9F0vkGQ7khAIk.AQABAAIAAAAm-06blBE1TpVMil8KPQ41w9B6RzkC9WfFOcRnPO-ZEoud6Ma5rn2WD0b4M8V-64aKic_fNgLbgdN-gS1aGNzQRWcrVG9socY61R4_Ii3pJLSKgDCAEDI57ShCUpfvuvgYuATrtt76zFwRodj--34G1w5hQxWdOXHrncMEWFG5qpU5MY84t1p3ECcVrlhFq9p9vUQbvn09DeVgSpFy4UYtqzLWZE1wR4VrWNknrZUA11xMP7FPHU32DHpJCwhfubY8J0vbKrNAtQg5FEKBOwV806dpLg9Z-ETdt8Riy4_gTm8iYfPJHboAL-yvjT4cIclWAgXAH7RsC1Z73rSajCx8q08SZikcQkd2BK_M1qA2LgjvJQSY47SorgXCOtZmKzp0MyiFkwY6rQJBBpgHvTfHInSRh1sXb_ljrMtAH9uTLxSwcUVwKuZSu_6SP17VPNFv4e86ez89fbVLkXw_bKvuzdubcDiIFRgyU5tFsznTHTZERv5IP3OPMgRjsZddHMEZ21sM80tIHESwUEZm_SV6Ddlx3P7fBz6L0Ea3oG1AZwog8_Kb1xlTmdyYguGkp6mIBXta7WFEFiRlXRZDIKot4ByVWlP9ME6upVahYZUL6xyCE2XpUr3hO3i7X1jLj5iy1LKVUkB1NEOS-ve1aYuoQ42YdlzEPyjt8tDmUFGKSyg4dMIbJ2EQy1U-w5EvxswMmJvWjvULxYDVJbu-Vgcg2N8FdZ307WPmvT8wtBNC7iA9FmaLCttVGu4I-pkpHg7MKw2jSTKVVnVzXqiui-zPUc9bxvFlUNTvQdfxAthDFSAA&state=tZCQGq72SYkbjckPjvgAcZZYnYGOCpSnIeTBKQphzQQ&session_state=3f5b0921-93d3-47e7-8f77-d5fae175580c HTTP/1.1

Which gives the following response

HTTP/1.1 302 Found
Date: Fri, 12 Jun 2020 19:59:33 GMT
Server: Apache
Strict-Transport-Security: max-age=31536000; includeSubdomains
X-Frame-Options: SAMEORIGIN
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Cache-Control: no-cache, no-store
Pragma: no-cache
X-Frame-Options: DENY
X-Frame-Options: DENY
Location: somtodayleerling://oauth:443/callback?code=eyJ6aXAiOiJERUYiLCJjdHkiOiJKV1QiLCJlbmMiOiJBMjU2R0NNIiwiYWxnIjoiZGlyIn0..VdR_CESqKlkK4Xzw.BZyamfT4hehkFmX1_JLux0cJNTtRQUWPRI4OLLKX20ZlNL4WzLW5ym9C7xCPcWSQaq6rwoqsD23AWggb7jN2QrjLelGJmEsuEovVXL0LKls1ypVC2xt51KGficjWjvPMZDZsm1yjtbGb-NeuXlHvz8kb9N0j7kG2FiuJs5H2fAZwomsAWNpDLFu4FpqnLJhbuUi6mMaLh8BC1z7af_Cd1QXrHs4iWuFdeu6D17MWLcpVEO0jweWJn_c7t6B0D02u5y9uO9e-rHMxmXDdbt_Klhvw04rvPSOUnvOkSB0tytXj-X6JlOThp7fQMjjZ83AXD0WY0uSnBftH9Q_zZDhQ4ImcX3qEHyB_jJAK-xatdwpQmblVZ56VSgcrLXYAfilBo31hPLkzPo3Vx9J7kV9TSDhGIKoTIf9xqUulRr0XRBnrxOTpRDx29HDEguLvgW-uwn8T1MIEeh85_NG2rPqIRqVoh0LDEUAEozDIkNgNe_7wYCFblVfxuDdDKUpXj6xHzNIG6EefdCBNu7f2wsnY0bu6z6cZOke8M2Uj3lnXTg5t42kWVOGminvheKGYTw5Lkd8LN0UAqudd1UQRAVCT4t62zMwgj4poHe10KN243S9zLfcGRQzhXmwbcyv8Xn6w7dSRPIQIAt2X-ARByp-EzojfY3jnbEnYjOz-6ERsXMu1e7fLWUAMtCb22ZvkRnkGRUAg5K2K8dqgUkWQoCTu8QYDTztjBDzE5HFC_DAcIMVWgXvIp0VIyQLBeumdUB562u6e0LkSWegbuAVAz59hFwshIXEFLXNKNbDkM0Zy_LLer3YpHFpNxeNvQ1VEPuGEPWC6HftjI68M3HWJ0Bh0vaaSzTJ5Ny6lp1xhrKCLYuFAHNX5FMktIembMNVyv_8Sm9K2oXhdvkClNE0LnEJNN9c54FIVFxDEEzh03D-tiqaYucAOjrdDZ20x0NnNGaBDflj3HSWOuGsCh_cz44xX3WbyCJiHWQ_LgJ6JrPD8-WXnLsH-iXBwuOqsRcFf29lC.AKx_1wrE1iOccXhutWeywQ
Content-Length: 0
Set-Cookie: authentication=; Path=/oidc; Max-Age=0; Expires=Thu, 01-Jan-1970 00:00:00 GMT
X-Robots-Tag: none
X-UA-Compatible: IE=Edge
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive

With somtodayleerling:// presumably being the target url of the app.

ChielChiel avatar Jun 12 '20 20:06 ChielChiel

That's very interesting, it could be the access token, a refresh token or an ID token. Was this request made with the app or with the browser?

elisaado avatar Jun 12 '20 21:06 elisaado

Well, at least on iOS, in the app, it opens a safari webview in which the entire login process takes place. From this webview the somtodayleerling:// request is made.

ChielChiel avatar Jun 12 '20 22:06 ChielChiel

I see, I have found a new grant_type called authorization_code which is linked to this!

elisaado avatar Jun 12 '20 22:06 elisaado

When I try to use your code I get:

{
    "error_description": "Invalid grant: Token has expired",
    "error": "invalid_grant"
}

So I think the code you mentioned can actually be used to fetch an access_token

elisaado avatar Jun 12 '20 22:06 elisaado

I get the same request made on my android when I try to use our school's new SSO function, I will try to throttle the connection so I get to use the code myself.

elisaado avatar Jun 12 '20 22:06 elisaado

I think it will still be possible to authenticate even with SSO, but it will be very ugly (saving Set-Cookie headers, etc)

elisaado avatar Jun 12 '20 22:06 elisaado

The tenant cookie is just base64 of the school uuid :) We only need to save JSESSIONID :)

elisaado avatar Jun 12 '20 22:06 elisaado

Wow great to see all these updates! Good work!

ChielChiel avatar Jun 12 '20 22:06 ChielChiel

This is the problem I'm having: everything is different for every school the microsoft oauth service works very differently from the idpcluster of stichtingcarmelcollege

There is no easy way to fix this issue

elisaado avatar Jun 13 '20 00:06 elisaado

Right, i see. Btw wjat exactly do you mean with “idpcluster”?

Secondly, can’t we let the admin, who will use these api to log users in, specify some of the username and password field names, so you can post that data easily?

Not sure if possible, but most request libraries allow you to follow redirects and post data on the way.

ChielChiel avatar Jun 13 '20 09:06 ChielChiel

Btw, decrypting any string starting with "eyJ6aXAiOiJERUYiLCJjdHkiOiJKV1QiLCJlbmMiOiJBMjU2R0NNIiwiYWxnIjoiZGlyIn0" or something like this is just a base64 encode of {"zip":"DEF","cty":"JWT","enc":"A256GCM","alg":"dir"}. JWT is apparently a Json Web Token. And this: Authorization: Basic RDUwRTBDMDYtMzJEMS00QjQxLUExMzctQTlBODUwQzg5MkMyOnZEZFdkS3dQTmFQQ3loQ0RoYUNuTmV5ZHlMeFNHTkpY could be a key to decrypt that the rest of the string.

Maybe that string holds all of the encrypted content like username, access token and whatever. However I haven't been able to decrypt A256GCM.

And curl "https://production.somtoday.nl/oauth2/token" -d "grant_type=refresh_token&refresh_token=[token] gives the following response: {"error_description":"Invalid request: Unexpected number of Base64URL parts, must be three","error":"invalid_request"}.

However, notice the .. in Location: somtodayleerling://oauth:443/callback?code=eyJ6aXAiOiJERUYiLCJjdHkiOiJKV1QiLCJlbmMiOiJBMjU2R0NNIiwiYWxnIjoiZGlyIn0..VdR_CESqKlkK4Xzw.BZyamfT4hehkFmX1_JLux0cJNTtRQUWPRI4OLLKX20ZlNL4WzLW5ym9C7xCPcWSQaq6rwoqsD23AWggb7jN2QrjLelGJmEsuEovVXL0LKls1ypVC2xt51KGficjWjvPMZDZsm1yjtbGb-NeuXlHvz8kb9N0j7kG2FiuJs5H2fAZwomsAWNpDLFu4FpqnLJhbuUi6mMaLh8BC1z7af_Cd1QXrHs4iWuFdeu6D17MWLcpVEO0jweWJn_c7t6B0D02u5y9uO9e-rHMxmXDdbt_Klhvw04rvPSOUnvOkSB0tytXj-X6JlOThp7fQMjjZ83AXD0WY0uSnBftH9Q_zZDhQ4ImcX3qEHyB_jJAK-xatdwpQmblVZ56VSgcrLXYAfilBo31hPLkzPo3Vx9J7kV9TSDhGIKoTIf9xqUulRr0XRBnrxOTpRDx29HDEguLvgW-uwn8T1MIEeh85_NG2rPqIRqVoh0LDEUAEozDIkNgNe_7wYCFblVfxuDdDKUpXj6xHzNIG6EefdCBNu7f2wsnY0bu6z6cZOke8M2Uj3lnXTg5t42kWVOGminvheKGYTw5Lkd8LN0UAqudd1UQRAVCT4t62zMwgj4poHe10KN243S9zLfcGRQzhXmwbcyv8Xn6w7dSRPIQIAt2X-ARByp-EzojfY3jnbEnYjOz-6ERsXMu1e7fLWUAMtCb22ZvkRnkGRUAg5K2K8dqgUkWQoCTu8QYDTztjBDzE5HFC_DAcIMVWgXvIp0VIyQLBeumdUB562u6e0LkSWegbuAVAz59hFwshIXEFLXNKNbDkM0Zy_LLer3YpHFpNxeNvQ1VEPuGEPWC6HftjI68M3HWJ0Bh0vaaSzTJ5Ny6lp1xhrKCLYuFAHNX5FMktIembMNVyv_8Sm9K2oXhdvkClNE0LnEJNN9c54FIVFxDEEzh03D-tiqaYucAOjrdDZ20x0NnNGaBDflj3HSWOuGsCh_cz44xX3WbyCJiHWQ_LgJ6JrPD8-WXnLsH-iXBwuOqsRcFf29lC.AKx_1wrE1iOccXhutWeywQ

When I remove one . it gives the following response {"error_description":"Invalid request: Invalid serialized JWE object: Missing fourth delimiter","error":"invalid_request"}`

ChielChiel avatar Jun 13 '20 11:06 ChielChiel

I'd like you to answer my question in #6

elisaado avatar Jun 13 '20 12:06 elisaado

The token you've found (somtodayleerling://oauth:443/callback?code=eyJ6aXAiOiJERUYiLCJjdHkiOiJKV1QiLCJlbmMiOiJBMjU2R0NNIiwiYWxnIjoiZGlyIn0..VdR_CESqKlkK4Xzw.BZyamfT4hehkFmX1_JLux0cJNTtRQUWPRI4OLLKX20ZlNL4WzLW5ym9C7xCPcWSQaq6rwoqsD23AWggb7jN2QrjLelGJmEsuEovVXL0LKls1ypVC2xt51KGficjWjvPMZDZsm1yjtbGb-NeuXlHvz8kb9N0j7kG2FiuJs5H2fAZwomsAWNpDLFu4FpqnLJhbuUi6mMaLh8BC1z7af_Cd1QXrHs4iWuFdeu6D17MWLcpVEO0jweWJn_c7t6B0D02u5y9uO9e-rHMxmXDdbt_Klhvw04rvPSOUnvOkSB0tytXj-X6JlOThp7fQMjjZ83AXD0WY0uSnBftH9Q_zZDhQ4ImcX3qEHyB_jJAK-xatdwpQmblVZ56VSgcrLXYAfilBo31hPLkzPo3Vx9J7kV9TSDhGIKoTIf9xqUulRr0XRBnrxOTpRDx29HDEguLvgW-uwn8T1MIEeh85_NG2rPqIRqVoh0LDEUAEozDIkNgNe_7wYCFblVfxuDdDKUpXj6xHzNIG6EefdCBNu7f2wsnY0bu6z6cZOke8M2Uj3lnXTg5t42kWVOGminvheKGYTw5Lkd8LN0UAqudd1UQRAVCT4t62zMwgj4poHe10KN243S9zLfcGRQzhXmwbcyv8Xn6w7dSRPIQIAt2X-ARByp-EzojfY3jnbEnYjOz-6ERsXMu1e7fLWUAMtCb22ZvkRnkGRUAg5K2K8dqgUkWQoCTu8QYDTztjBDzE5HFC_DAcIMVWgXvIp0VIyQLBeumdUB562u6e0LkSWegbuAVAz59hFwshIXEFLXNKNbDkM0Zy_LLer3YpHFpNxeNvQ1VEPuGEPWC6HftjI68M3HWJ0Bh0vaaSzTJ5Ny6lp1xhrKCLYuFAHNX5FMktIembMNVyv_8Sm9K2oXhdvkClNE0LnEJNN9c54FIVFxDEEzh03D-tiqaYucAOjrdDZ20x0NnNGaBDflj3HSWOuGsCh_cz44xX3WbyCJiHWQ_LgJ6JrPD8-WXnLsH-iXBwuOqsRcFf29lC.AKx_1wrE1iOccXhutWeywQ)

can be used to fetch an access token, by calling

https://production.somtoday.nl/oauth2/token with the following x-www-form-urlencoded body:

grant_type:authorization_code
code:<the code you got from somtodayleerling://oauth:443/callback?>
//scope:openid
client_id:D50E0C06-32D1-4B41-A137-A9A850C892C2
redirect_uri:somtodayleerling://oauth/callback
code_verifier:<some random string, I think>

elisaado avatar Jun 13 '20 14:06 elisaado

Aight, well, when I run the following command I get {"error_description":"Invalid grant: Token has expired","error":"invalid_grant"}

I even tried getting a new key by going here: https://somtoday.nl/oauth2/authorize?response_type=code&client_id=D50E0C06-32D1-4B41-A137-A9A850C892C2&redirect_uri=somtodayleerling://oauth/callback&scope=openid&tenant_uuid=cbeab658-c9e6-4a54-b419-8f682f82ea54&prompt=login&session=no_session&code_challenge=uLYUyUVgId8zjbxN4oLNCMa-DzcF_5nRnFOkZensf_w&code_challenge_method=S256 Which is the webpage that is opened when you login with sso in the somtoday app

curl -v "https://production.somtoday.nl/oauth2/token" -d "grant_type=authorization_code&code=$code&scope=openid&client_id=D50E0C06-32D1-4B41-A137-A9A850C892C2&redirect_uri=somtodayleerling://oauth/callback&code_verifier=cbeab658-c9e6-4a54-b419-8f682f82ea54\\87c63403-49c9-48db-b5a4-458f515a2695"

ChielChiel avatar Jun 13 '20 15:06 ChielChiel

Yeah you need to authorize with a password first and also supply the cookies

elisaado avatar Jun 13 '20 16:06 elisaado

I am unable to get it working consistently, and I have no clue how I would handle different authentication providers.

Could you provide a proxy or network log of your full log-in with the credentials and tokens blanked out?

elisaado avatar Jun 16 '20 12:06 elisaado

I have tried to login with an extensive curl php script. However after login at my schools login system it would just create a loop of login screens, strange. In what kind of format would you like to see all those logs?

ChielChiel avatar Jun 18 '20 16:06 ChielChiel

Are you guys still actively working on it? I still have my SOM Credentials but SOM is down for the weekend now. When it's back up I could go ahead and try if I can get authentication to work again.

christosk92 avatar Jul 25 '20 07:07 christosk92

PS: Back in the day, SOM just stored their auth credentials in their app, which you could just easily decompile for the Android app.

christosk92 avatar Jul 25 '20 07:07 christosk92

Hi, not actively anymore as I have just graduated. However, if you could find a way to automate the SSO authentication flow it would be a Great Leap Forward!

ChielChiel avatar Jul 25 '20 13:07 ChielChiel

Hey guys,

@christosk92 Any help would be greatly appreciated, what I have in mind for now is the following flow: any implementation library of this documentation would do something along the lines of

  • return link that has to be opened in the browser
  • user logs in to their oauth provider
  • user copies the url containing the oauth code back to the app/program
  • library fetches the access_token from the code that's in the url

it's all standard oauth flow until the "user copies url" part because I have found no way to alter the redirect_uri (I think?.. it's been a while since I've worked on this).

elisaado avatar Jul 25 '20 15:07 elisaado

@ChielChiel sorry for not replying to the comment you made on the 18th of June, I was kind of busy (toetsweek) and then forgot about it.

elisaado avatar Jul 25 '20 15:07 elisaado

Do you guys still need a SOM account? Mine still works

christosk92 avatar Jul 27 '20 08:07 christosk92

Yes, that'd definitely help

elisaado avatar Jul 27 '20 10:07 elisaado

I've sent them to your mail linked to your GitHub

christosk92 avatar Jul 28 '20 07:07 christosk92

Thank you! I'll continue the work when somtoday is back up

elisaado avatar Jul 28 '20 19:07 elisaado

I wonder what kind of maintenance would require them to go offline for 6 days :thinking:

elisaado avatar Jul 28 '20 19:07 elisaado