Learn what Felgo offers to help your business succeed. Start your free evaluation today! Felgo for Your Business

OAuth 2.0 Plugin

Let your users authorize with external OAuth 2.0 providers.

User Authorization and Authentication

Use OAuth 2.0 to authorize and optionally use OpenID Connect (OIDC) to authenticate your users.

System UI

QML API to access native authorization interfaces.

Overview

OAuth 2.0 is the industry-standard protocol for authorization. Read more at https://oauth.net/2/.

The OAuth 2.0 plugin supports the following features:

  • Authentication: Let your users sign in with their accounts with external OAuth 2.0 providers.
  • Persistence: Store tokens securely and provide access via an easy-to-use declarative QML API.
  • Automatic token refresh: Refresh access tokens automatically via a refresh tokens.
  • PKCE extension: Prevent against authorization code interception.
  • OpenID Connect Token: Retrieve, decode and validate an OpenID Connect token.

Example Usage

The following example sets up an OAuth2Client client to authorize a user with a GitHub app.

When the user clicks on "Login", it opens the GitHub login page in a system browser.

Afterwards, you can use OAuth2Client::getValidAccessToken() to obtain a valid token for REST API calls.

 import QtQuick
 import Felgo

 App {
   id: app

   readonly property url userUrl: "https://api.github.com/user"

   property var userData: null

   OAuth2Client {
     id: oauth

     // adapt to your own GitHub app
     authUrl: "https://github.com/login/oauth/authorize"
     tokenUrl: "https://github.com/login/oauth/access_token"
     callbackUrl: "felgooauthtest://callback"

     clientId: "<your client ID>"
     clientSecret: "<your client secret>"

     // GitHub does not support PKCE
     pkceType: OAuth2Client.None

     // show consent dialog on every login
     promptType: OAuth2Client.Consent

     // Startup path 1: no prior session — user never logged in, or last logout was clean.
     onSessionNotFound: {
       showLoginScreen()
     }

     // Startup path 2: session restored — token was valid or a startup refresh succeeded.
     // Safe to make authenticated API calls from here.
     onAccessTokenReady: {
       // we are now authenticated and can use the accessToken
       errorText.text = ""
       getUser()
     }

     // Startup path 3: session existed but startup token refresh failed (e.g. refresh token expired).
     // Also fires after a successful interactive authenticate() call.
     onIsAuthenticatedChanged: {
       if(isAuthenticated) {
         // we are now authenticated and can use the accessToken
         errorText.text = ""
         getUser()
       }
       else {
         showLoginScreen()
       }
     }

     onAuthenticationError: message => {
                              console.log("OAuth2: authentication error:", message)
                              errorText.text = "Auth error: " + message
                            }
   }

   /////////////////////////////

   NavigationStack {

     FlickablePage {
       title: "GitHub OAuth 2.0 Test"
       flickable.contentHeight: content.height

       Column {
         id: content
         width: parent.width

         AppText {
           width: parent.width
           wrapMode: Text.WrapAtWordBoundaryOrAnywhere
           text: "Access Token: " + oauth.accessToken
         }

         AppText {
           width: parent.width
           wrapMode: Text.WrapAtWordBoundaryOrAnywhere
           text: "Refresh Token: " + oauth.refreshToken
         }

         Flow {
           width: parent.width

           AppButton {
             text: "Login"
             enabled: !oauth.isAuthenticated

             onClicked: oauth.authenticate()
           }

           AppButton {
             text: "Refresh tokens"
             enabled: oauth.isAuthenticated && !!oauth.refreshToken

             onClicked: oauth.requestRefreshedTokens()
           }

           AppButton {
             text: "Logout"
             enabled: oauth.isAuthenticated

             onClicked: {
               oauth.logout()
               userData = null
             }
           }
         }

         AppText {
           id: errorText
           text: ""
           width: parent.width
           wrapMode: Text.WrapAtWordBoundaryOrAnywhere
         }

         AppText {
           visible: !!userData
           text: "Logged in as: " + userData?.login
           width: parent.width
           wrapMode: Text.WrapAtWordBoundaryOrAnywhere
         }

         AppImage {
           visible: !!userData
           source: userData?.avatar_url ?? ""
           width: parent.width
           fillMode: Image.PreserveAspectFit
         }
       }
     }
   }

   function getUser() {
     // Get GitHub user data: https://docs.github.com/en/rest/users

     // Use getValidAccessToken() to obtain a non-expired token before making API calls.
     // This automatically refreshes the token if it has expired.
     oauth.getValidAccessToken(function(token) {
       if (!token) {
         errorText.text = "No valid access token available"
         return
       }

       HttpRequest
         .get(userUrl)
         .set("Accept", "application/vnd.github+json")
         // add access bearer token as HTTP authentication:
         .set("Authorization", "Bearer " + token)
         .set("X-GitHub-Api-Version", "2022-11-28")
         .then(res => {
                 userData = JSON.parse(res.text)
                 console.log("User data:", JSON.stringify(userData, null, "  "))
               })
         .catch(err => {
                 console.log("Could not get user:", err.status, err.code, err.message, err.response.text)
                })
     })
   }
 }

Token Refresh

The OAuth 2.0 standard supports automatic token refresh.

After authorization, the OAuth2Client item requests an access token from the token API. The API can also provide an optional OAuth2Client::refreshToken.

The refresh token is generally longer-lived and the plugin can use it to request an updated access token.

Using getValidAccessToken()

The recommended way to obtain a token before making API calls is OAuth2Client::getValidAccessToken(). It checks whether the current token is still valid and automatically refreshes it if necessary before passing it to your callback:


          
Qt_Technology_Partner_RGB_475 Qt_Service_Partner_RGB_475_padded