OAuth, Redirect URI and other weird creatures lazarus / 38-Networking and Web Programming ---------------------------------------------------------------------- Ñuño_Martínez · 2020-05-29 09:24 Actually not sure if this is the best sub-forum.  Move it if you think so. Trying to summarize. I started to do streaming through Twitch.tv and I realized there are not desktop applications for Linux.  I'm using ffmpeg from a terminal, but this doesn't allow too much control and you have to have a web- browser open to your channel to control some stuff. So I was wondering to create a simple (ha!) application to do some management over the streaming, even calling ffmpeg instead of using the terminal, but as I've read public Twitch.tv API uses OAuth and forces to have a "Redirect URI".  About OAuth I have no idea how does it work or if it's possible to do such thing using Free Pascal (Indy? Synapse? ...).  About the URI, here they suggest to use a local webserver embedded in the application (I know it is possible to create a local webserver but I don't see why it is necessary). Of course I'll ask in Twitch developers forum but I'm pretty sure they don't know what Pascal is so I first ask here for help and opinion, specially because I don't actually know what to ask them.  I did very few network programming with Free Pascal so I'm a bit lost. ---------------------------------------------------------------------- rvk · 2020-05-29 11:16 Quote from: Ñuño_Martínez on May 29, 2020, 11:24:07 amAbout the URI, here they suggest to use a local webserver embedded in the application (I know it is possible to create a local webserver but I don't see why it is necessary). A local webserver is necessary because the oauth opens up a browser to their authentication page. After the user accepts, the user gets redirected to your own url with the access token in the url itself. Without that, you can't get to the access token because you usually don't have access to the browser data. Your  "Redirect URI" can look like http://localhost:1500 and you'll only need to listen on port 1500 for the incoming connection. You can present a simple page with "my app now has access" or something. ---------------------------------------------------------------------- Thaddy · 2020-05-29 12:10 There's a good OAuth2 example in trunk (probably also 3.2.0) ---------------------------------------------------------------------- Leledumbo · 2020-05-29 17:52 Additionally, current OAuth version is a bit liberal, in the sense that the flow may be customized a bit. Most won't directly give you the access token in that redirect URI, but an authorization code that you must exchange with an actual access token. Instagram is a crazier example as even after that you're given a short term access token only, which you must exchange again with long term one if you're planning to use it for a longer time. Even so, eventually access token will and should expire for security. So you will have to regularly refresh the access token to get a new one. A sane OAuth implementation should provide this endpoint, where you should give a refresh token to get a new access token. Typically both are returned when you exchange the authorization code. You can play around here to get a better understanding of how the protocol in each flows work. Here's a little redirect server example (not directly working as you will need to substitute the placeholder values with something real): Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program fpoauthclientexample; {$mode objfpc}{$H+} uses  SysUtils,  httpdefs,  httproute,  fpjson,  jsonparser,  fphttpclient,  fpHTTPApp; procedure ExchangeAuthCodeWithAccessToken(ARequest: TRequest; AResponse: TResponse);var  LCode,LOAuthRes,LAccessToken: String;  LJSONRes: TJSONObject;  LAccessTokenNode: TJSONData;begin  LCode := ARequest.QueryFields.Values['code'];  if LCode = '' then begin    AResponse.Code := 400;    AResponse.ContentType := 'application/json';    AResponse.Content := '{"message":"code parameter is not provided or empty"}';  end else begin    try      LOAuthRes := TFPHTTPClient.SimpleFormPost('http://some.where/oauth/acc ess_token','client_id=xxx&client_secret=yyy&grant_type=authorization_c ode=' + LCode);      LJSONRes := TJSONObject(GetJSON(LOAuthRes));    if Assigned(LJSONRes) then begin        LAccessTokenNode := LJSONRes.FindPath('access_token');        LAccessToken := LAccessTokenNode.AsString;        // now you have the access token, store it somewhere secure      end;    except      on e: Exception do begin        AResponse.Code := 500;        AResponse.ContentType := 'application/json';        AResponse.Content := '{"message":"' + e.Message + '"}';      end;    end;  end;end; begin  HTTPRouter.Regist erRoute('/exchange',@ExchangeAuthCodeWithAccessToken);  Application.Initialize;  Application.Port := 9999;  Application.Run;end. ---------------------------------------------------------------------- Ñuño_Martínez · 2020-05-31 10:34 Thanks for the comments and tips.  I'll follow the links and read the examples, and ask more question if needed.