Partner-Center-DotNet-Samples
Partner-Center-DotNet-Samples copied to clipboard
Non interactive user auth
Feature Request
Maybe I have missunderstand the SecureAppModel and what I looking for is already existing. The year before, when MFA was not mandatory, I could use User Auth by directly getting access token with user credential like this :
"Authentication": {
"ApplicationId": "mypartnercenterappid",
"ApplicationSecret": "mypartnercenterappsecret",
"ApplicationDomain": "xxxxxxxxx.onmicrosoft.com",
"User": "[email protected]",
"Password": "myuserpassword",
"TenantId": "tenant of my organization",
"Authority": "https://login.windows.net",
"ResourceUrl": "https://graph.windows.net",
"PartnerServiceApiRoot": "https://api.partnercenter.microsoft.com"
}
public async Task<IPartner> GetPartnerConnection()
{
if (_aggregatePartner != null && !_aggregatePartner.Credentials.IsExpired())
return _aggregatePartner;
PartnerService.Instance.ApiRootUrl = Configurations.Authentication.PartnerServiceApiRoot;
IPartnerCredentials partnerCredentials = await PartnerCredentials.Instance.GenerateByUserCredentialsAsync(Configurations.Authentication.ApplicationId, await GetUserToken());
_aggregatePartner = PartnerService.Instance.CreatePartnerOperations(partnerCredentials);
return _aggregatePartner;
}
private async Task<AuthenticationToken> GetUserToken()
{
HttpResponseMessage response = await _client.PostAsync($"{Configurations.Authentication.Authority}/{Configurations.Authentication.TenantId}/oauth2/token", new FormUrlEncodedContent(new Dictionary<string, string>
{
{ "scope", "openid" },
{ "grant_type", "password" },
{ "resource", Configurations.Authentication.PartnerServiceApiRoot },
{ "client_id", Configurations.Authentication.ApplicationId },
{ "client_secret", Configurations.Authentication.ApplicationSecret },
{ "username", Configurations.Authentication.User },
{ "password", Configurations.Authentication.Password }
}));
if (!response.IsSuccessStatusCode)
throw new Exception($"Can't get partner center token for user \"{Configurations.Authentication.User}\"");
JObject auth = JsonConvert.DeserializeObject<JObject>(await response.Content.ReadAsStringAsync());
string accessToken = auth["access_token"].Value<string>();
long expiresOn = auth["expires_on"].Value<long>();
return new AuthenticationToken(accessToken, new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddSeconds(expiresOn).ToLocalTime());
}
It was so simple, now, since arround october I can't use my GetUserToken
function because response.IsSuccessStatusCode
is false.
My application is an API that allow our customer's users to do actions on partner centers like : listing there users account and add/remove licence on user account. For this, application auth is not sufficient, so I have to use User Auth. I want to use a service account that auto-login in background as before. Is there any solution ?
I realize this is a year old and I hope you managed to solve your problem. We had the same issue and it caused quite a bit of problem when MFA and secure model got adopted as we needed each of our employees to authorize every request we were automating.
We solved this by having a user authorize once, storing their token in the Azure Key Vault then having the refresh token used to keep doing automated tasks to the partner center in the background.
https://docs.microsoft.com/en-us/partner-center/develop/partner-center-authentication#partner-consent
This describes the process we followed hope it helps for others!
Feature Request
Maybe I have missunderstand the SecureAppModel and what I looking for is already existing. The year before, when MFA was not mandatory, I could use User Auth by directly getting access token with user credential like this :
"Authentication": { "ApplicationId": "mypartnercenterappid", "ApplicationSecret": "mypartnercenterappsecret", "ApplicationDomain": "xxxxxxxxx.onmicrosoft.com", "User": "[email protected]", "Password": "myuserpassword", "TenantId": "tenant of my organization", "Authority": "https://login.windows.net", "ResourceUrl": "https://graph.windows.net", "PartnerServiceApiRoot": "https://api.partnercenter.microsoft.com" }
public async Task<IPartner> GetPartnerConnection() { if (_aggregatePartner != null && !_aggregatePartner.Credentials.IsExpired()) return _aggregatePartner; PartnerService.Instance.ApiRootUrl = Configurations.Authentication.PartnerServiceApiRoot; IPartnerCredentials partnerCredentials = await PartnerCredentials.Instance.GenerateByUserCredentialsAsync(Configurations.Authentication.ApplicationId, await GetUserToken()); _aggregatePartner = PartnerService.Instance.CreatePartnerOperations(partnerCredentials); return _aggregatePartner; } private async Task<AuthenticationToken> GetUserToken() { HttpResponseMessage response = await _client.PostAsync($"{Configurations.Authentication.Authority}/{Configurations.Authentication.TenantId}/oauth2/token", new FormUrlEncodedContent(new Dictionary<string, string> { { "scope", "openid" }, { "grant_type", "password" }, { "resource", Configurations.Authentication.PartnerServiceApiRoot }, { "client_id", Configurations.Authentication.ApplicationId }, { "client_secret", Configurations.Authentication.ApplicationSecret }, { "username", Configurations.Authentication.User }, { "password", Configurations.Authentication.Password } })); if (!response.IsSuccessStatusCode) throw new Exception($"Can't get partner center token for user \"{Configurations.Authentication.User}\""); JObject auth = JsonConvert.DeserializeObject<JObject>(await response.Content.ReadAsStringAsync()); string accessToken = auth["access_token"].Value<string>(); long expiresOn = auth["expires_on"].Value<long>(); return new AuthenticationToken(accessToken, new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddSeconds(expiresOn).ToLocalTime()); }
It was so simple, now, since arround october I can't use my
GetUserToken
function becauseresponse.IsSuccessStatusCode
is false.My application is an API that allow our customer's users to do actions on partner centers like : listing there users account and add/remove licence on user account. For this, application auth is not sufficient, so I have to use User Auth. I want to use a service account that auto-login in background as before. Is there any solution ?
Have you figure out how to change the console app sdk to be non interactive? Could you share how you did it?
I have give up and just generate a token/refresh token manually first time.
Then I have stock the access token/refresh token in a SQL table and my app update theses tokens automatically when they expire.
A proper solution may exists but I don't found