#1 2015-04-30 18:03:22

jgb
Member
From: Canada
Registered: 2014-11-07
Posts: 7

Implementing OAuth2

I am restarting this discussion in a new thread to cover the implementation of OAuth2. The original discussion was here.

I know there is at least some interest in this. My submission in the previous thread has gone quiet. Not sure if it's because my work is terrible, incomplete or both? I am hoping it is just because it is not immediately clear as to how to get OAuth2 up and running easily, and it is this that I will address in this discussion.

tldr; For the really impatient:

Get the core implemetation: OAuth2Authentication.pas

  1. Include OAuth2Authentication.pas in you Delphi project 

  2. Derive a class from one of the 4 grant types:

    1. TOAuth2AuthorizationGrant

    2. TOAuth2ImplicitGrant

    3. TOAuth2ResourceOwnerPasswordGrant - (example based on this one)

    4. TOAuth2ClientCredentialsGrant

  3. Override the minimum required methods:

    1. GetAuthToken() - you validate credentials and return a token

    2. GetSession() - you validate the token and return a TAuthSession (or descendant)

    3. AuthSuccess() - you store the auth_token, refresh_token and expires for future use (authenticating subsequent requests)

    4. //TODO: Refresh token handling goes here

  4. In your TSQLRestServer (or descendant) constructor register your authentication class:

    constructor TMySQLRestServer.Create(aModel: TSQLModel);
    begin
      inherited;
      AuthenticationRegister([TMyAuthentication]);
    end;
  5. Incorporate the 3 changes below into mORMot.pas

The example


Let me first briefly outline my requirements. We use mORMot only as a server to provide json resources from an existing, large, legacy DB2 database. The client is an Android application but there is the expectation that the mORMot server with provide resources for other integration's. With that said I have done some pretty extensive modifications to the server (via descendants) to provide a flexible architecture for our developers to create new server (endpoints) and extend existing endpoints with additional resources.

Our system is also internal (for now) and is expected to operate within our customers corporate network (or VPN). This affects security considerations.

Authentication
Although the OAuth2 implementation is not complete, it follows the spec (https://tools.ietf.org/html/rfc6749) to the letter.

AFAIK, the OAuth2 authentication process is similar to the mORMot system.

The spec outlines 4 grant types. The first, Authorization Code Grant, is probably the most used for web site collaboration and the primary use case envisioned by the creators of this. However, in my situation I want to connect with an existing user/pass database and provide authentication tokens. This is a common pattern and is supported well on Android. OAuth2 provides 3 alternative grant types to support additional cases, after reviewing the grant types I decided on "Resource Owner Password Grant", IMHO this matches both our needs and matches the mORMot authentication system well.

The process occurs like so:

In order to access a resource the client must have an Authorization bearer token in the HTTP header e.g.:

  AUTHORIZATION: Bearer FD94A9F2D4644F619CD3705B98371EF2

if this is not present the server will return "401 Unauthorized" (currently mORMot would produce 403 Forbidden). The header will contain a

  WWW-Authenticate: Bearer realm="mORMot Server"

The body will contain a json document with 1 to 3 data elements:

{
  error: "Unauthorized"                                     //REQUIRED
  error_description: "Something more descriptive" //OPTIONAL
  error_uri: "uri for more info about this error"     //OPTIONAL
}

In order to get a token the client must request a token at the /auth endpoint (same as mORMot?). Include a standard basic authentication header and also include the user/pass in the body (Obviously a secure connection is recommended for this). Personally I don't understand why they want the credentials twice. This implementation looks at the "Authorization: Basic ..." header only.

A successful call to /auth will result in something like:

{
    "access_token": "0C49867F502F455CA300916F158E6CDB",
    "token_type": "bearer",
    "expires_in": 86400,
    "refresh_token": "00F075FB3AE541E2984345CF88470A00"
}

The client should store that access_token and use it as the bearer token until another 401 is received at which point the refresh token logic should kick in.

I would like to make this a full and complete implementation. But... I am not going to bother if there is no interest. I expect to start the refresh token logic very soon. as for client support and other grant types, that will depend on interest.

Best regards,
Jeff


PS: Just realized there was something missing from my original post:

Add a new method to TSQLRestServerAuthentication (to allow each authentication class to handle failures individually)

TSQLRestServerAuthentication = class  
...
public 
  ...
  function AuthenticationFailed(Ctxt: TSQLRestServerURIContext): boolean; virtual;
end;

is implemeted like so (to ensure backwards compatibility):

function TSQLRestServerAuthentication.AuthenticationFailed(Ctxt: TSQLRestServerURIContext): boolean;
begin  
  Ctxt.Call.OutStatus := HTML_FORBIDDEN;
  Result := True;
end;

then in TSQLRestServerURIContext we modify AuthenticationFailed() to handle multiple authentication instances:

procedure TSQLRestServerURIContext.AuthenticationFailed;
var
  aSession: TAuthSession;
  i: integer;
begin
//JGB
  if Server.HandleAuthentication then
  begin
    Session := CONST_AUTHENTICATION_SESSION_NOT_STARTED;
    Server.fSessions.Lock;
    try
      aSession := nil;
      if Server.fSessionAuthentication<>nil then
        for i := 0 to Server.fSessionAuthentications.Count-1 do
          if Server.fSessionAuthentication[i].AuthenticationFailed(Self) then
            Break;
    finally
      Server.fSessions.UnLock;
    end;
   end;

  // 401 Unauthorized response MUST include a WWW-Authenticate header,
  // which is not what we used, so here we won't send 401 error code but 403
  //JGB - We handle the out status in the TSQLRestServerAuthentication classes
  //JGB - Call.OutStatus := HTML_FORBIDDEN;
end;

The TOAuth2AbstractAuthentication class uses this method to return authentication failures consistent with the OAuth2 spec.

Offline

#2 2015-04-30 20:53:43

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,660
Website

Re: Implementing OAuth2

I will work on OAuth2 this weekend.

Thanks for sharing.

Offline

#3 2016-09-26 09:51:44

Purvarshi
Member
Registered: 2016-09-22
Posts: 1

Re: Implementing OAuth2

Hi,


I am interested in this. I want to implement SSO Authentication using OAuth. please share some more detail on this.

Thanks & Regards
Purvarshi jain

Offline

#4 2016-09-26 10:21:22

esmondb
Member
From: London
Registered: 2010-07-20
Posts: 299

Re: Implementing OAuth2

1

Offline

#5 2016-10-19 09:50:07

hnb
Member
Registered: 2015-06-15
Posts: 290

Re: Implementing OAuth2

ab wrote:

I will work on OAuth2 this weekend.

Thanks for sharing.

@ab any progress ? Seems like OAuth2 work takes more than one weekend ;)

Last edited by hnb (2016-10-19 10:37:47)


best regards,
Maciej Izak

Offline

#6 2018-11-13 19:47:04

Daniel
Member
Registered: 2016-12-08
Posts: 23

Re: Implementing OAuth2

Has anyone done anything more with this ?

Offline

#7 2018-11-19 20:39:44

erick
Member
Registered: 2015-09-09
Posts: 155

Re: Implementing OAuth2

Almost, very close, I've got externalize authentication working for HTMl5/AJAX web clients.  I've tested it with SAML and CAS, but I do not have a production OIDC server to ensure I've got it all working perfectly.  My site is preparing an ADFS system which is in beta testing right now, and I hope to have completed against it by Christmas.

Erick

Offline

#8 2022-07-19 11:25:23

squirrel
Member
Registered: 2015-08-13
Posts: 155

Re: Implementing OAuth2

Does anybody still have copies of these gists available? I need a mormot server with oauth authentication and was hoping this would be something to build on.  But the gists seem to be all gone already.

Offline

#9 2022-07-19 12:35:17

Prometeus
Member
From: USA
Registered: 2020-11-20
Posts: 46

Re: Implementing OAuth2

squirrel wrote:

Does anybody still have copies of these gists available? I need a mormot server with oauth authentication and was hoping this would be something to build on.  But the gists seem to be all gone already.

email sent

Offline

#10 2022-07-19 12:38:25

squirrel
Member
Registered: 2015-08-13
Posts: 155

Re: Implementing OAuth2

Thank you so much!

Offline

#11 2022-07-28 19:05:26

JD
Member
Registered: 2015-08-20
Posts: 118

Re: Implementing OAuth2

Prometeus wrote:
squirrel wrote:

Does anybody still have copies of these gists available? I need a mormot server with oauth authentication and was hoping this would be something to build on.  But the gists seem to be all gone already.

email sent

Hi there Prometheus,

Could you please send me the copies by email too?

Thanks a lot

JD

Offline

#12 2022-07-28 19:55:55

Prometeus
Member
From: USA
Registered: 2020-11-20
Posts: 46

Re: Implementing OAuth2

Email sent

Offline

#13 2022-07-28 20:05:06

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,660
Website

Re: Implementing OAuth2

Perhaps a new public gist may be more convenient.

Offline

#14 2022-07-28 21:35:33

Prometeus
Member
From: USA
Registered: 2020-11-20
Posts: 46

Re: Implementing OAuth2

ab wrote:

Perhaps a new public gist may be more convenient.

..

The file is not mine, so I don't feel comfortable doing this

Offline

#15 2023-02-20 06:06:38

PierceNg
Member
From: Singapore
Registered: 2023-01-29
Posts: 10
Website

Re: Implementing OAuth2

@Prometeus, if you still have the gist content, please send me a copy by email. Thanks.

Offline

#16 2023-02-24 12:48:23

PierceNg
Member
From: Singapore
Registered: 2023-01-29
Posts: 10
Website

Re: Implementing OAuth2

@Prometeus, I got your mail. Thank you. (My mail provider failed to deliver my reply mail.)

Offline

#17 2023-03-23 09:54:45

mrbar2000
Member
From: Brazil
Registered: 2016-10-26
Posts: 90

Re: Implementing OAuth2

I world like a copy too please. Cannyou put on github?

Offline

#18 2023-04-04 08:41:43

squirrel
Member
Registered: 2015-08-13
Posts: 155

Re: Implementing OAuth2

Has anybody had any success implimenting this oauth2.0 into their project?

Offline

#19 2024-01-31 09:49:04

alexkam75
Member
Registered: 2020-01-28
Posts: 4
Website

Re: Implementing OAuth2

https://gist.github.com/jbendixsen/392e … cation-pas
The link is not working. Can someone send a OAuth2 (or JWT) implementation to mORMot?

Offline

#20 2024-01-31 18:23:10

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,660
Website

Re: Implementing OAuth2

JWT is pretty straightforward.

Offline

Board footer

Powered by FluxBB