question

Alex-6426 avatar image
1 Vote"
Alex-6426 asked Alex-6426 answered

SaaS Resolve API failing with 403

Hi, I am trying to test out the SaaS Resolve API to activate a subscription to a marketplace offering my team is developing, using the steps listed here: https://docs.microsoft.com/en-us/azure/marketplace/partner-center-portal/pc-saas-fulfillment-api-v2#resolve-a-purchased-subscription

I am able to find my offering on the marketplace (with our users being the preview audience), and clicking configure account from Azure portal correctly takes me to our SaaS offering landing page with the marketplace token in the URL - (`https://my.website/landing-page?token=<ms-token>`)

We are then using MSAL library to get the user authorization token, which makes a POST call to https://login.microsoftonline.com/common/oauth2/v2.0/token with the following form data:

client_id: <our Azure App ID>
redirect_uri: https://my.website/landing-page
scope: openid profile
code: <code>
code_verifier: <code_verifier>
grant_type: authorization_code
client_info: 1
client-request-id: 039a3648-53ca-432c-b005-311a777048c7


This returns a 200, and we are then saving the response.accessToken to be used in the SaaS resolve API:

POST https://marketplaceapi.microsoft.com/api/saas/subscriptions/resolve?api-version=2018-08-31

Request Headers:
Authorization: 'Bearer ' + accessToken
Content-Type: application/json
x-ms-marketplace-token: decodeURIComponent(<token in url>),


However, this is returning 403 Forbidden back. Is there any insight into what we are doing wrong? If it helps, the x-ms-requestid response header generated by MS during the resolve subscription request is 0fb4fe86-f4bb-4125-ae42-a4cd18ad098d

azure-active-directoryazure-ad-multi-factor-authentication
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

alfredorevilla-msft avatar image
0 Votes"
alfredorevilla-msft answered

I see you're using the authorization grant flow to request a token but you need to use the client credentials flow as described in Get the token with an HTTP POST.


Please let us know if this answer was helpful to you. If so, please remember to mark it as the answer so that others in the community with similar questions can more easily find a solution.


5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Alex-6426 avatar image
1 Vote"
Alex-6426 answered Alex-6426 edited

Thanks @alfredo-revilla-msft , this is helpful. Looking over the client credentials flow, it looks like the token acquisition is meant to happen on the web server instead of client? I have updated the flow to work as follows:

1) https://my.website/landing-page?token=<ms-token> is opened from the Azure Portal subscription manage

2) The user is redirected to https://login.microsoftonline.com/adminconsent?client_id=<app-id>&state=12345&redirect_uri=https://my.website/landing-page (from https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow#request-the-permissions-from-a-directory-admin)

3) After logging in successfully, the user is redirected back to https://my.website/landing-page

4) I then call our server API that proxies to token acquisition on the backend (from https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow#first-case-access-token-request-with-a-shared-secret). Here is the proxy call done from our backend:

POST https://login.microsoftonline.com/common/oauth2/v2.0/token

Headers:
Content-Type: application/x-www-form-urlencoded

Body:
grant_type: 'client_credentials',
client_id: <app-id>,
client_secret: <app-secret>,
scope: 'https://graph.microsoft.com/.default'

This returns an access_token in the response, which I return back to our web client

5) I call the SaaS resolve API with the bearer token returned above, and the ms token provided in step 1. This still returns 403 forbidden.

If it's helpful, the generated x-ms-requestid response header value is 001bdd37-0bfe-4760-93bf-834c5297ecb0



I think I may be misunderstanding the flow still. When I acquire the token server side (step 4), I am not passing through any of the data from steps 2-3, and since this is server side none of the client side login during step 2-3 should matter? Thank you for your help.

5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Alex-6426 avatar image
0 Votes"
Alex-6426 answered

UPDATE:

Thank you for contacting us to help clarify the issue. We have been able to resolve the issue of 403 Forbidden when trying to resolve a SaaS subscription by making the following updates to the client credentials flow from my last post:

1) Changing the scope value in the body of the token acquisition call from https://graph.microsoft.com/.default to 20e940b3-4c77-4b0b-9a53-9e16a1b010a7/.default (corresponding documentation at https://docs.microsoft.com/en-us/azure/marketplace/partner-center-portal/pc-saas-registration#request-body)

2) Updating the token acquisition URL from https://login.microsoftonline.com/common/oauth2/v2.0/token to https://login.microsoftonline.com/<azure-tenant-id>/oauth2/v2.0/token

We are now able to resolve the token and use the response data to activate a subscription to our SaaS offering. Thanks again!

5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.