OAuth 2 provider for Frappe Apps

Hi @revant_one
I would like to thank you for your explanation about OAuth 2 . I already used it in my mobile app., and followed your instructions in this topic and in the others, but I want more explanation about revoke_token,the purpose? and when I should do it ?
Also , Is the OAuth 2 always depends on the cookies and sessions data?
the last question is about refresh_token, I can not have any response from it, althought I used the responded token from get_token as mentioned here https://frappe.io/docs/user/en/guides/integration/using_oauth
but I got this msg

Thanks
Maysaa

1 Like

revoke_token endpoint revokes the bearer_token. Revoke token after using refresh_token and getting a new valid token, revoke the expired token. This way it is cleaned up from server

  • Any client connected using it will be revoked.
  • If token is expired, refresh_token remains valid.
  • If token is revoked, refresh_token canā€™t be used and
  • Revoked tokens will be cleaned up from the server

No it doesnā€™t depend on cookies or session, It just checks for valid access token in header instead of cookie in header.

The only place where it depend on browser and cookies is the ā€œauthorization screenā€; the allow/deny app screen.

Under
OAuth Client > Advance Settings > Grant Type select Authorization Code
and
Response Type select Code

Implicit/Token doesnā€™t allow refreshing the token.

1 Like

Thanks @revant_one
But about refresh_token, I already fill the same values in my site, and the same response

Can you share the Postman requests in Python / CURL?

Here my request and the same result :frowning:

@revant_one I have some trubbles with OAuth 2 authorization way,
Now I used it in my mobile app as the following steps:

  • get the authorization code and login using frappe.integrations.oauth2.authorize
  • get the token of that code by frappe.integrations.oauth2.get_token
  • call the first frappe api ā€œapi/resource/Attendanceā€ with Authorizaton: Bearer <bearer_token>

now the problem is when another user tried to login and call an api, it will execute it with the last authorized user!
Is it important to do the authorize and get the token process in each api call?
give me the right way and concept to do that in frappe plz
Thanks
Maysaa

The token is tied to user, if that specific token is used it is like making request as that user.

As long as user is logged in to a session on a browser, authorize endpoint is accessed through browser with existing session.

No, you can use the token for 1 hr. Then refresh it.

My case is with Mobile app that call some apiā€™s from frappe, now I noticed that the requests depends on the user session, but in my Mobile app i just used the Auth 2 authorization to get a token in order to be in all the user request. and when i apply this logic, I faced a problem with multi user login, as my frappe server always using the last bearer token stored in the auth table, so when any user call an api it will called with the last stored token whatever whom the logged user.
I can not solve it by this protocol, but I need a solution to complete my app perfectly, Is this way is right for my case as you see?

You can achieve multi user login by storing multiple tokens. A token for user in your mobile app.

Only for the Authorization part the session is required. the screen where user is asked the app is trying to access resource, and user has to allow or deny.

In case you use the Library it clears the webview before showing the authorization screen.
(i.e. clear cache, remove cookies)

In this case the webview for logging in always shows login screen instead of Allow Deny screen or session login.

Once the token is with mobile app, just use it for accessing resource. refresh it in case it expires, no need to login again.

If you donā€™t wish to use web view, create your own view and make a request from there, use ROPC grant, in this case you make request with username and password to get bearer token.

DO NOT store username and password, just store the bearer token and refresh it as required.

More : OAuth 2.0 : Resource Owner Password Credentials Grant by revant Ā· Pull Request #5226 Ā· frappe/frappe Ā· GitHub

If it is Android/Java app use this library GitHub - mntechnique/OAuth2Authenticator

Also noticed, you are using GET request for creating a token?

Use POST request in case of get_token endpoint

1 Like

This is a very interesting feature, and thanks to revant_one for all of the work that went into it.

Iā€™m struggling to understand the instructions here, likely because of my limited understanding of how OAuth works. I know I have some homework to do, but I was hoping to understand the possibilities before I dig too deep. Using this, is it possible to create a single sign on system using Frappe/ERPNext as an identity provider for other compatible services? I have a minimal LDAP server set up right now, but as more and more of our data is moving into ERPNext itā€™d be great to start treating that as the authoritative repository.

Yes, It is possible to create a single sign on for compatible services.
The client app needs to implement ā€œoauth2 clientā€ library available in its language.

Intention of feature :

  • Standardized way to achieve authorization for third party apps like Mobile Apps, SPAs, Web Apps.
  • Third party developers / apps need not store password, which is important for some enterprises.
  • Authentication and authorization is delegated to frappe server.
  • Main purpose is to enable easy secure REST API Integration for ERPNext users (even cloud users).

Over LDAP, Frappe Framework will provide 2FA to your users. Thanks to Manqala for the feature.

Other things to consider :

  • Frappe can also act as an OAuth 2.0 client instead of Identity Provider. Use Social Login Key.
  • If there is already existing provider you are using you can add it to frappe. Refer recent PR - fairlogin social ID provider by rasos Ā· Pull Request #6096 Ā· frappe/frappe Ā· GitHub
  • Frappe already connects with Google, Facebook, Github, Microsoft, Salesforce, fairapps.net as an oauth2 client.
  • You can add a provider if it is available to public. Refer above PR. (Keycloak, IdentityServer4, Gluu are good publicly available candidates to add if youā€™re a user)
  • If your provider is private, you can add your own custom Social Login Key through custom frappe app.
1 Like

Thanks @revant_one!

I got ERPNext working as a client to githubā€™s IdP at one point, so I think I have a handle on the general premise. So, to get this set up, I need:

  • for the whole ecosystem, one Social Login Key doc to define how the security assertion request process works (defining transaction URIs, etc), and
  • per client service, one OAuth Client doc to define parameters for that particular client (access scope, etc.)

Is that correct?

Add OAuth Client on IDP

Add Social Login Key on Client.

Repeat for each additional client.

Try it. Lot of things have been shared on forum and docs to help you.

Start a new thread if you cannot find answers.

2 Likes

Weā€™ve been using this integration to great effect, and it has really put Frappe at the center of our information systems. Recently, however, weā€™ve hit a bit of a wall.

Iā€™m trying to understand how to get an id_token, which the documentation seems to suggest should come along with the access_token if openid is included as a scope. Iā€™m not finding that to be the case for implicit grant flows. Is this by design?

response_type=token only responds with access_token even if the scope has openid in it.

response_type=token%20id_token or any other related grant is not implemented.

Checkout oauthlib Welcome to OAuthLibā€™s documentation! ā€” OAuthLib 3.2.1 documentation if you wish to implement it.

1 Like

Thanks for the clarification, @revant_one. Iā€™ll take a look at the implementation needs over the next couple of days to see if Iā€™m able to setup the necessary bits.

Iā€™ve spent several hours on this now, but unfortunately without much to show yet. Iā€™m struggling, I think, to fully grok the division of labour between the frappe.integrations.oauth2 endpoint methods, the frappe.oauth backend, and the oauthlib.oauth2 library functions.

To get response_type=token%20id_token implemented, would amending the frappe.integrations.oauth2.authorize RPC be enough, or does this require architectural changes deeper? Iā€™m committed to adding this and getting it sent upstream, but I think I might be in a bit over my head!

Edit: Specifically, though I think I have a reasonable understanding of how the id_token is assembled in the get_token endpoint, Iā€™m not really seeing where the parameters are getting added to the callback url from the authorize endpoint.

The whitelisted functions can remain as they are. You need to implement methods for whatever is needed in OAuthWebRequestValidator in frappe/oauth.py

read more:

extend the frappe/tests/test_oauth20.py as per the features you add.

Just a thought, Implict grant flows donā€™t make sense for frappe/erpnext. They will let you have a token on browser app but then you have restriction related to CORS. Enabling CORS on frappe/erpnext backend is not a good idea.

@revant_one Thank you for taking the effort in compiling all these details here. I went through it and the documentation.

I had one query for which I couldnā€™t resolve. Is grant_type password supported in frappe? I tried with postman against a client and I am not able to get it to work.

I need to generate a login token using users username and password via API.

Yes it is supported.