I'm in the process of implementing InApp purchases (subscriptions) with Huawei In App SDK.
Everything's good except token verification against Huawei's servers.
My code is similar to that here: https://developer.huawei.com/consumer/en/doc/development/HMS-References/iap-api-order-service-purchase-token-verification-v4
I'm using an access token which is obtained like so: https://developer.huawei.com/consumer/en/doc/development/HMS-Guides/38054564 - the same code to obtain access tokens already works with Huawei Push SDK by the way.
For verification, my code sends requests to https://orders-dre.iap.hicloud.com/applications/purchases/tokens/verify with this data:
{
"purchaseToken":"00000175799be0e659fc74cb06...5.8.5650",
"productId":"annual"
}
The response comes back as:
{"responseCode":"6","responseMessage":"rights invalid"}
The FAQ here https://developer.huawei.com/consumer/en/doc/development/HMS-Guides/iap-FAQ recommends:
"You are advised to check whether the app ID used for obtaining AccessToken is the same as the app ID associated with purchaseToken in the request".
Now I only have one project / one set of Client ID / Client Secret, so it matches the app ID, by definition.
What could be wrong?
PS - this is happening with a test subscription, i.e. purchased by a user account that's set up as a test account.
According to the code part you provided, you are using Purchase Token Verification for the Order Service, and you should use API for Verifying the Purchase Token for the Subscription Service.
Purchase Token Verification for the Order Service applies only to non-subscription purchases. It is used to verify the purchase token in the payment result sent from the Huawei IAP server to ensure payment accuracy.
API for Verifying the Purchase Token for the Subscription Service applies only to subscriptions. It is used to check whether a product has been successfully purchased and is within the validity period.
Verifying the Purchase Token for the Subscription Service:
Parameter: subscriptionId;purchaseToken
RequestUrl: {rootUrl}/sub/applications/v2/purchases/get
rootURL:
China: https://subscr-drcn.iap.hicloud.com
Germany: https://subscr-dre.iap.hicloud.com
Singapore: https://subscr-dra.iap.hicloud.com
Russia: https://subscr-drru.iap.hicloud.com
AppTouch site of Germany: https://subscr-at-dre.iap.dbankcloud.com
We're currently working on a project that requires the users' accounts to be linked to one of our client's services via the oAuth2 authorization flow.
However, there is the possibility that tokens expire before the expires_in duration that's returned with the token from the oAuth2 token endpoint, or that the user simply revokes the token/authorization. In that case a new token needs to be fetched via the refresh-token-flow, or the Account needs to be re-linked altogether.
Is there some way for us to indicate to Google (in the HTTP response returned by the fulfilment backend, or via some other way) that the access_token is no longer valid and needs to be refreshed, or that the Account needs to be relinked?
For instance, with Alexa, it is possible to return an "Account Linking Card" in the HTTP response along with the actual speech that's read back to the user.
This "card" then starts the account linking process on Amazon's side(even if the Account was already linked before). Is there an equivalent to this in the Actions SDK?
If there is no way for us to indicate to Google that the Account Linking is no longer valid and needs to be redone or refreshed, is there at least some way to programmatically "unlink" an Account (which would then automatically trigger the Account Linking process on the next invocation)?
Is it possible to create a public OAuth Client id that never expires in Smartsheet using their simple developer account they provide?
They provide trial accounts, but my concern is what happens with the OAuth client when the account expires? Will the client expire to?
Developer accounts are fully featured and can participate in the OAuth flow.
The account would need to remain active for the client id to continue working. Trial accounts are just that - trials, so naturally you wouldn't want to setup anything permanent with an account you don't intend to keep.
You might be confusing client ids (essentially an identifier for your app) with access tokens? The client id would remain the same for the life of your app. Access tokens would need to be refreshed periodically. See the documentation for details.
TL;DR When using google oauth on desktop app, what to save on disk to avoid repeated sign in? Save the google user id? or the token? or an session id?
I'm creating an little desktop app, whitch must authenticate to my REST API server. I'm using google oauth2 for that.
The idea is, that when the desktop app will be authentivated, it generates some data that will be send to my server. The server will store the data with the google user id received from https://www.googleapis.com/userinfo/v2/me.
On the first run of the desktop app, it will open the default browser, with and url for my server and start an local http server. then:
my server will redirect the browser to google (with the clientid, secret, etc.)
user logs in and it will be redirected back to the server with the oauth code
server uses the code to get the token, and then the user profile and stores the token and the profile in db, then redirects the browser to localhost with an paramerer
the desktop app catches the parameter and stores it in an file on the disk
next time the desktop app will start it only reads the file for the parameter to send the generated data with it to my server
my question is: what the parameter should be? the google user id? the oauth token? an generated session id for this desktop app? or something else?
when it will be the google user id, it can conveniently sent the data with the user id and the rest server will just store it in db as is. but I don't think it's safe
when it will be the token, the rest server has to with every request also get the user profile from google with the token. and imho sending the token with every request isn't safe either
generating an session id means to store it with the user and the token on the server and the desktop app will just store it and send it with every request. but I don't know if it's safe to do that
As it's normally the case in software development you have a couple of options depending on requirements.
The mandatory requirement is that your client (desktop) application needs to send something to your REST API so that the API can perform up to two decisions:
Decide who the user is.
Decide if the user is authorized to perform the currently requested action.
The second step may not be applicable if all authenticated users have access to exactly the same set of actions so I'll cover both scenarios.
Also note that, for the first step, sending the Google user ID is not a valid option as that information can be obtained by other parties and does not ensure that the user did authenticate to use your application.
Option 1 - Authentication without fine-grained authorization
Either always sending the id_token or exchanging that token with your custom session identifier both meet the previous requirement, because the id_token contains an audience that clearly indicates the user authenticated to use your application and the session identifier is generated by your application so it can also ensure that. The requests to your API need to use HTTPS, otherwise it will be too easy for the token or session ID to be captured by an attacker.
If you go with the id_token alternative you need to take in consideration that the token will expire; for this, a few options again:
repeat the authentication process another time; if the user still has a session it will indeed be quicker, but you still have to open a browser, local server and repeat the whole steps.
request offline_access when doing the first authentication.
With the last option you should get a refresh token that would allow for your application to have a way to identify the user even after the first id_token expires. I say should, because Google seems to do things a bit different than the specification, for example, the way to obtain the refresh token is by providing access_type=offline instead of the offline_access from OpenID Connect.
Personally, I would go with the session identifier as you'll have more control over lifetime and it may also be simpler.
Option 2 - Authentication + fine-grained authorization
If you need a fine-grained authorization system for your REST API then the best approach would be to authenticate your users with Google, but then have an OAuth 2.0 compliant authorization server that would issue access tokens specific for your API.
For the authorization server implementation, you could either:
Implement it yourself or leverage open source components
⤷ may be time consuming, complex and mitigation of security risks would all fall on you
Use a third-party OAuth 2.0 as a servive authorization provider like Auth0
⤷ easy to get started, depending on amount of usage (the free plan on Auth0 goes up to 7000 users) it will cost you money instead of time
Disclosure: I work at Auth0.
There should be no problem sending the access_token with every request since they are created for that purpose and are thus short lived. You can use the Google Authorization Server endpoint to verify a token instead of using it to do a request for a users profile.
If you're only relying on Google for authentication, here's how your workflow can look:
the client (desktop application, in your case) retrieves the
Google id_token following the user's log in, and then sends it to
the server
the server validates the integrity of said token and extracts the user's profile data; this could mean a simple GET on Google's endpoint to verify this token: https://www.googleapis.com/oauth2/v3/tokeninfo?id_token={0}
On subsequent requests, nothing should change really, except that the user's login process will be automated (since he's given permissions & all), and thus much faster. #danielx is right, there's no problem with sending the token each and every time.
I'd like to create this simple model:
user registers and Firebase stores email & password
user pays with PayPal to access protected content
Firebase gets notified by PayPal the user has paid & logs this
paying user logs in with his credentials & Firebase authorizes access to the protected content; non-paying users are denied access
What is the bare minimum amount of functionality needed to leverage Firebase's backend and make this work?
Depends on your exact requirements (ie, are 5 or 15 minute delays acceptable) but you can get started super quickly using Zapier
https://zapier.com/zapbook/firebase/paypal/
You would setup the zap using your secret firebase and paypal keys, setting the zap to update a property on the user's profile (be sure to use Firebase security rules to limit write access to that property) which says they have paid.