1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980openUtilstypet={grant_type:string;scope:Scopes.tlist;code:string;client_id:string;client_secret:stringoption;redirect_uri:Uri.t}letmake~grant_type~scope~redirect_uri~codeclient=let{Client.id;secret;_}=clientin{grant_type;scope;code;client_id=id;client_secret=secret;redirect_uri}letto_body_stringt=["grant_type",[t.grant_type];"scope",[Scopes.to_scope_parametert.scope];"code",[t.code];"client_id",[t.client_id];"client_secret",[t.client_secret|>ROpt.get_or~default:"secret"];"redirect_uri",[t.redirect_uri|>Uri.to_string]]|>Uri.encoded_of_query(* The Authorization Server MUST validate the Token Request as follows:
Authenticate the Client if it was issued Client Credentials or if it uses
another Client Authentication method, per Section 9. Ensure the Authorization
Code was issued to the authenticated Client. Verify that the Authorization
Code is valid. If possible, verify that the Authorization Code has not been
previously used. Ensure that the redirect_uri parameter value is identical to
the redirect_uri parameter value that was included in the initial
Authorization Request. If the redirect_uri parameter value is not present
when there is only one registered redirect_uri value, the Authorization
Server MAY return an error (since the Client should have included the
parameter) or MAY proceed without an error (since OAuth 2.0 permits the
parameter to be omitted in this case). Verify that the Authorization Code
used was issued in response to an OpenID Connect Authentication Request (so
that an ID Token will be returned from the Token Endpoint).
*)letof_body_stringbody=letquery=Uri.query_of_encodedbody|>Uri.with_queryUri.emptyinletgt=Uri.get_query_paramquery"grant_type"inlets=Uri.get_query_paramquery"scope"inletc=Uri.get_query_paramquery"code"inletci=Uri.get_query_paramquery"client_id"inletclient_secret=Uri.get_query_paramquery"client_secret"inletru=Uri.get_query_paramquery"redirect_uri"inmatchgt,s,c,ci,ruwith|Somegrant_type,Somescope,Somecode,Someclient_id,Someredirect_uri->Ok{grant_type;scope=Scopes.of_scope_parameterscope;code;client_id;client_secret;redirect_uri=redirect_uri|>Uri.of_string}|Somegrant_type,None,Somecode,Someclient_id,Someredirect_uri->Ok{grant_type;scope=[];code;client_id;client_secret;redirect_uri=redirect_uri|>Uri.of_string}|Some_,Some_,Some_,Some_,None->Error(`Msg"missing redirect_uri")|Some_,Some_,Some_,None,Some_->Error(`Msg"missing client_id")|Some_,Some_,None,Some_,Some_->Error(`Msg"missing code")|None,Some_,Some_,Some_,Some_->Error(`Msg"missing grant_type")|_->Error(`Msg"More than 1 missing")