Get AuthToken for SharepointOnline in dotnet core - sharepoint

I'm able to get an auth token for Sharepoint in Postman using the following parameters:
URL : https://accounts.accesscontrol.windows.net/{tenantId}/tokens/OAuth/2
Method: POST
Headers :
- Content-type: application/json
Body :
Resource: 00000003-0000-0ff1-ce00-000000000000/{myorganization}.sharepoint.com#{tenantId}
grant_type: client_credentials
client_id: {appId}#{tenantId}
client_secret: {myclientsecret}
Now, I'm trying to reproduce this POST http call in dotnet core, but I'm getting always a 400 (Bad request) response..
Here is my code :
var body = new AuthBodySPO
{
Resource = resource,
client_id = appId,
client_secret = appSecret,
grant_type = "client_credentials"
};
using (var client = new HttpClient())
using (var request = new HttpRequestMessage(HttpMethod.Post, url))
{
var json = JsonConvert.SerializeObject(body);
using (var stringContent = new StringContent(json, Encoding.UTF8, "application/json"))
{
request.Content = stringContent;
using (var response = await client
.SendAsync(request, HttpCompletionOption.ResponseHeadersRead)
.ConfigureAwait(false))
{
response.EnsureSuccessStatusCode();
}
}
}
Anyone has an idea ?
Thanks

Related

POST to asp.net web api fails from nodejs but works from postman

Please I have been battling with this issue. I have some api controllers and they work well with postman but posting from nodejs using axios I have errors. Here's my axios code:
var postData = JSON.stringify(req.body);
var postdataToString = JSON.parse(postData);
postdataToString['grant_type'] = "password";
delete postdataToString['submit'];
var PostBody = JSON.stringify(postdataToString);
and
let response = axios({
method: 'POST',
url: url,
proxy: undefined,
data: PostBody,
headers:{'Content-Type': 'application/x-www-form-urlencoded'},
headers:{'Accept': 'application/json'}
})
The error output from the console shows the json data is correct.
Here is a piece from the api code:
public async Task<IHttpActionResult> Register(UserModel userModel)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
IdentityResult result = await _repo.RegisterUser(userModel);
the error is invalid request.
Thanks for your help

C# - Get Graph access token - using Client ID, Client Secret, Scope with Client Delegated Permissions

I have got the graph delegated permissions on my AAD app Client ID.
Now, I want to request access token for the graph calls using app Client ID, app Client Secret and Graph Scope in the backend without user consent.
I have tried the below approach but getting a Bad Request, can anyone guide me in the right way of what I'm doing wrong?
string graphAccessUrl = "https://login.microsoftonline.com/tenant.onmicrosoft.com/oauth2/v2.0/token";
_httpClient.DefaultRequestHeaders.Accept.Clear();
_httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded"));
List<KeyValuePair<string, string>> values = new()
{
new KeyValuePair<string, string>("grant_type", "client_credentials"),
new KeyValuePair<string, string>("client_id", appClientId),
new KeyValuePair<string, string>("client_secret", appClientSecret),
new KeyValuePair<string, string>("scope", scope) //graph scope
};
HttpContent c = new FormUrlEncodedContent(values);
//GET Method
try
{
HttpResponseMessage response = _httpClient.PostAsync(new Uri(graphAccessUrl), c).Result;
if (response.IsSuccessStatusCode)
{
string responseString = response.Content.ReadAsStringAsync().Result;
TokenData reponseObj = JsonConvert.DeserializeObject<TokenData>(responseString);
string accessToken = reponseObj.access_token;
return accessToken;
}
else
{
throw new ArgumentException("Failed to get authtoken due response code." + response.StatusCode);
}
}
catch (Exception ex)
{
throw new ArgumentException(ex.Message);
}
Unless your scenario is a little different to mine, the usual approach is to exchange the current user's access token for a Graph access token, as in my code sample. My code is in Node.js but you'll be able to translate it to C# easily enough.
*
* Use the Azure specific 'on behalf of' flow to get a token with permissions to call the user info endpoint
*/
private async _getGraphAccessToken(accessToken: string): Promise<string> {
try {
const formData = new URLSearchParams();
formData.append('grant_type', 'urn:ietf:params:oauth:grant-type:jwt-bearer');
formData.append('client_id', this._configuration.graphClient.clientId);
formData.append('client_secret', this._configuration.graphClient.clientSecret);
formData.append('assertion', accessToken);
formData.append('scope', 'openid profile email');
formData.append('requested_token_use', 'on_behalf_of');
const options = {
url: this._configuration.tokenEndpoint,
method: 'POST',
data: formData,
headers: {
'content-type': 'application/x-www-form-urlencoded',
'accept': 'application/json',
},
};
const response = await axios.request(options as AxiosRequestConfig) as any;
return response.data.access_token!;
} catch (e) {
// Report Graph errors clearly
throw ErrorFactory.fromUserInfoTokenGrantError(e, this._configuration.tokenEndpoint);
}
}
In OAuth terms this is a user assertion, to swap an incoming access token for another access token for the same user. Some further notes on setup in this blog post.

How to get authentication token using MSAL library for Azure DevOps REST API call?

I want to get Azure DevOps PAT list using REST API call. I'm using Azure Function App (JavaScript/NodeJS).
I want to get "PAT" list using the REST API. So I'm using the PAT List REST API, but I'm not able to get the list. I'm using the MSAL library for For Authentication. Using this MSAL library I'm able to get the authentication token although I'm unable to get "PAT List".
How we get "PAT List" ?
For more clarity I'm adding below our code. If I'm making any mistakes then anyone can rectify me.
const config = require('../config');
const rp = require('request-promise');
const msal = require('#azure/msal-node');
module.exports = async function (context, req) {
const clientId = 'config.DEFAULT_CLIENT_ID';
const clientSecret = 'config.DEFAULT_CLIENT_SECRET';
const tenantId = 'config.DEFAULT_TENANT_ID';
let authorityHostUrl = 'https://login.windows.net';
let authorityUrl = authorityHostUrl + '/' + tenantId;
const configuration = {
auth: {
clientId: clientId,
authority: authorityUrl,
clientSecret: clientSecret
}
};
// Create msal application object
const cca = new msal.ConfidentialClientApplication(configuration);
// With client credentials flows permissions need to be granted in the portal by a tenant administrator.
// The scope is always in the format "<resource>/.default"
const clientCredentialRequest = {
scopes: ["499b84ac-1321-427f-aa17-267ca6975798/.default"], // replace with your resource
};
const credentials = await cca.acquireTokenByClientCredential(clientCredentialRequest);
const tokenType = credentials.tokenType;
const token = credentials.accessToken;
const apiToken = `${tokenType} ${token}`; // 'Bearer <token>'
let url = `https://vssps.dev.azure.com/{organization}/_apis/tokens/pats?api-version=6.1-preview.1`;
const header = {
Authorization: `${apiToken}`
};
const result = await rp({
url: url,
json: true,
headers: header,
mode: 'cors',
cache: 'no-cache',
method: 'GET'
});
context.res = {
body: result
};
}
Output: After run the above code I'm getting the below result as HTML.
I'm not getting the proper response. Getting the above response as HTML view.

Create Azure Key Vault C# error remote server returned an error: (403) Forbidden

I was tried to create azure key vault through in the specified subscription.
Followed this article,
https://learn.microsoft.com/en-us/rest/api/keyvault/keyvaultpreview/vaults/createorupdate#examples
So I write the code in a console application and
my code,
var URI = "https://management.azure.com/subscriptions/00000000000000000000000000/resourceGroups/0000000/providers/Microsoft.KeyVault/vaults/KeyValutADj?api-version=2018-02-14-preview";
Uri uri = new Uri(String.Format(URI));
var token = await AuthHelper.KeyVaultAuthenticationAsync();
// Create the request
var httpWebRequest = (HttpWebRequest)WebRequest.Create(uri);
httpWebRequest.Headers.Add(HttpRequestHeader.Authorization, "Bearer " + token);
httpWebRequest.ContentType = "application/json";
httpWebRequest.Method = "PUT";
HttpWebResponse httpResponse = null;
string body = "{\"location\": \"centralus\",\"properties\": {\"tenantId\": \"00000000.onmicrosoft.com\",\"sku\": {\"family\": \"A\",\"name\": \"standard\"},\"accessPolicies\": [{\"tenantId\": \"0000000000.onmicrosoft.com\",\"objectId\": \"0000000000000000000000000000000\",\"permissions\": {\"keys\": [\"encrypt\",\"decrypt\",\"wrapKey\",\"unwrapKey\",\"sign\",\"verify\",\"get\",\"list\",\"create\",\"update\",\"import\",\"delete\",\"backup\",\"restore\",\"recover\",\"purge\"],\"secrets\": [ \"get\",\"list\",\"set\",\"delete\",\"backup\",\"restore\",\"recover\",\"purge\"],\"certificates\": [\"get\",\"list\",\"delete\",\"create\",\"import\",\"update\",\"managecontacts\",\"getissuers\",\"listissuers\",\"setissuers\",\"deleteissuers\",\"manageissuers\",\"recover\",\"purge\"] }}],\"enabledForDeployment\": true,\"enabledForDiskEncryption\": true,\"enabledForTemplateDeployment\": true}}";
try
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Accept.ParseAdd("application/json");
client.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36");
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
using (var stream = new MemoryStream())
using (var writer = new StreamWriter(stream))
{
writer.Write(body);
writer.Flush();
stream.Flush();
stream.Position = 0;
using (var content = new StreamContent(stream))
{
content.Headers.Add("Content-Type", "application/json");
var response = await client.PutAsJsonAsync(URI, content);
if (response.IsSuccessStatusCode)
{
}
else
{
}
}
}
}
}
But when run the console application , get the error
"The remote server returned an error: (403) Forbidden."
How to solve this issue?
"The remote server returned an error: (403) Forbidden."
The error message means you have not permission to add resource to azure.
I test and reproduce your problem in my site. After I Add permission in Subscriptions to user or the application which I has registered in Azure AD, I could create key vault correctly.
Also, you could get more details about how to registry AD App and assign role to application, please refer to document. After that we can get tenantId, appId, secretKey from the Azure Portal. Then we can use Microsoft.IdentityModel.Clients.ActiveDirectory SDK to get token for api authentication.
The way how to generate Bearer Token you could refer to the following code.
var appId = "0000000000000000000000000000000";
var secretKey = "******************************************";
var tenantId = "0000000000000000000000000000000";
var context = new AuthenticationContext("https://login.windows.net/" + tenantId);
ClientCredential clientCredential = new ClientCredential(appId, secretKey);
var tokenResponse = context.AcquireTokenAsync("https://management.azure.com/", clientCredential).Result;
var accessToken = tokenResponse.AccessToken;
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);
var baseUrl = new Uri($"https://management.azure.com/");
var requestURl = baseUrl +"subscriptions/b83c1ed3-c5b6-44fb-b5ba-2b83a074c23f/resourceGroups/joeyWebApp/providers/Microsoft.KeyVault/vaults/joeykeyvault5?api-version=2018-02-14-preview";
string body = "{\"location\": \"centralus\",\"properties\": {\"tenantId\": \"0000000000000000000000000000000\",\"sku\": {\"family\": \"A\",\"name\": \"standard\"},\"accessPolicies\": [{\"tenantId\": \"0000000000000000000000000000000\",\"objectId\": \"0000000000000000000000000000000\",\"permissions\": {\"keys\": [\"encrypt\",\"decrypt\",\"wrapKey\",\"unwrapKey\",\"sign\",\"verify\",\"get\",\"list\",\"create\",\"update\",\"import\",\"delete\",\"backup\",\"restore\",\"recover\",\"purge\"],\"secrets\": [ \"get\",\"list\",\"set\",\"delete\",\"backup\",\"restore\",\"recover\",\"purge\"],\"certificates\": [\"get\",\"list\",\"delete\",\"create\",\"import\",\"update\",\"managecontacts\",\"getissuers\",\"listissuers\",\"setissuers\",\"deleteissuers\",\"manageissuers\",\"recover\",\"purge\"] }}],\"enabledForDeployment\": true,\"enabledForDiskEncryption\": true,\"enabledForTemplateDeployment\": true}}";
var stringContent = new StringContent(body, Encoding.UTF8, "application/json");
var response = client.PutAsync(requestURl, stringContent).Result;
}

Error Origin URI when Uber API with Javascript

I'm developing an web application using uber API and I got some problems when I send request to uber API:
"No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin '...... our origin https url' is therefore not allowed access."
I set Origin URL (which is https link) in our app board and using below code to refresh token key:
parameters = {
'redirect_uri': 'my redirect link',
'refresh_token': "my refresh token",
'grant_type': 'refresh_token',
'client_secret': 'my secret client',
'client_id': 'my client ID'
};
var data = new FormData();
for (var item in parameters) {
data.append(item, parameters[item]);
};
var xhr = new XMLHttpRequest();
xhr.open('POST', 'https://login.uber.com/oauth/token', true);
xhr.onload = function() {
var data = JSON.parse(this.responseText);
console.log("access_token: " + data.access_token);
var refresh_token = data.refresh_token;
console.log("refresh_token: " + refresh_token);
};
xhr.send(data);
And one more information, that code running well before and error above just happen some days ago.
If you need details about my app board information please let me know.
Thanks for any helps!

Resources