OAuth access without GAS

Example getting OAuth access when the application is not behind GAS, for example a mobile app.

OAuthAPI helper functions

IMPORT com
IMPORT FGL OAuthAPI
IMPORT util

PUBLIC TYPE QueryUserInfoResponseBodyType DYNAMIC ARRAY OF RECORD
    user_id INTEGER,
    given_name STRING,
    family_name STRING,
    email STRING
END RECORD

# Error codes
PUBLIC CONSTANT C_SUCCESS = 0

PUBLIC FUNCTION QueryUserInfo(idp_url STRING, user_login STRING, user_password STRING) RETURNS(INTEGER, QueryUserInfoResponseBodyType)
    DEFINE fullpath base.StringBuffer
    DEFINE contentType STRING
    DEFINE req com.HTTPRequest
    DEFINE resp com.HTTPResponse
    DEFINE resp_body QueryUserInfoResponseBodyType
    DEFINE json_body STRING
    DEFINE expire INTEGER
    DEFINE meta OAuthAPI.OpenIDMetadataType
    
    CALL OAuthAPI.FetchOpenIDMetadata(5, ipd_url) RETURNING meta.*
    CALL OAuthAPI.RetrievePasswordToken(5, meta.token_endpoint, user_login, user_password, "profile") RETURNING access_token, expire 
    CALL OAuthAPI.initService(5, access_token)

    TRY

        # Prepare request path
        LET fullpath = base.StringBuffer.Create()
        CALL fullpath.append("/userinfo/v1/query")

        WHILE TRUE
            # Create oauth request and configure it
            LET req =
                OAuthAPI.CreateHTTPAuthorizationRequest(meta.userinfo_endpoint
                    SFMT("%1%2", Endpoint.Address.Uri, fullpath.toString()))

            # Perform request
            CALL req.setMethod("GET")
            CALL req.setHeader("Accept", "application/json")
            CALL req.DoRequest()

            # Retrieve response
            LET resp = req.getResponse()
            # Retry if access token has expired
            IF NOT OAuthAPI.RetryHTTPRequest(resp) THEN
                EXIT WHILE
            END IF
        END WHILE
        # Process response
        INITIALIZE resp_body TO NULL
        LET contentType = resp.getHeader("Content-Type")
        CASE resp.getStatusCode()

            WHEN 200 #Success
                IF contentType MATCHES "*application/json*" THEN
                    # Parse JSON response
                    LET json_body = resp.getTextResponse()
                    CALL util.JSON.parse(json_body, resp_body)
                    RETURN C_SUCCESS, resp_body
                END IF
                RETURN -1, resp_body

            OTHERWISE
                RETURN resp.getStatusCode(), resp_body
        END CASE
    CATCH
        RETURN -1, resp_body
    END TRY
END FUNCTION