Microsoft Graph
A Microsoft programmability model that exposes REST APIs and client libraries to access data on Microsoft 365 services.
10,715 questions
This browser is no longer supported.
Upgrade to Microsoft Edge to take advantage of the latest features, security updates, and technical support.
I am trying to use GraphApi to create a print job. It seems to be working if grant_type is authorization_code but doesn't work if grant_type is password and the error I am getting is not really helpful. The user is a Printer Administrator and the registered app has all the required permissions with admin consent.
Error:
Status Code: Forbidden
Microsoft.Graph.ServiceException: Code: UnknownError
Inner error:
AdditionalData:
date: 2021-12-08T17:21:59
request-id: 1bda2e07-7636-409a-a5dc-75c40bc64c2f
client-request-id: 1bda2e07-7636-409a-a5dc-75c40bc64c2f
ClientRequestId: 1bda2e07-7636-409a-a5dc-75c40bc64c2f
at Microsoft.Graph.HttpProvider.SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken)
at Microsoft.Graph.BaseRequest.SendRequestAsync(Object serializableObject, CancellationToken cancellationToken, HttpCompletionOption completionOption)
at Microsoft.Graph.BaseRequest.SendAsync[T](Object serializableObject, CancellationToken cancellationToken, HttpCompletionOption completionOption)
at WebApplication1.Controllers.HomeController.PrintJob(Boolean useCredentials)
at WebApplication1.Controllers.HomeController.AuthRedirect(String code)
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Logged|12_1(ControllerActionInvoker invoker)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
Here's a Sample Code:
async Task Main()
{
string tenantId = "TENANT ID GUID";
string clientId = "REGISTERED APP CLIENT ID GUID";
string clientSecret = "SECRET FROM REGISTERED APP";
string printerId = "PRINTER ID GUID";
string redirectUri = "https://localhost:44318/home/authredirect";
string scope = "openid offline_access https://graph.microsoft.com/.default";
string authorization_code = "AUTHORIZATION CODE FROM REDIRECT AFTER AUTHENTICATION";
using var client = new HttpClient();
var url = $"https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token";
HttpResponseMessage res;
bool useCredentials = true;
if (useCredentials)
{
res = await client.PostAsync(url, new FormUrlEncodedContent(new Dictionary<string, string>
{
{ "client_id", clientId },
{ "scope", scope },
{ "username", "USER EMAIL ADDRESS" },
{ "password", "USER PASSWORD" },
{ "grant_type", "password" },
{ "client_secret", clientSecret }
}));
}
else
{
res = await client.PostAsync(url, new FormUrlEncodedContent(new Dictionary<string, string>
{
{ "client_id", clientId },
{ "scope", scope },
{ "code", authorization_code },
{ "redirect_uri", redirectUri },
{ "grant_type", "authorization_code" },
{ "client_secret", clientSecret }
}));
}
var content = await res.Content.ReadAsStringAsync();
var token = System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, object>>(content);
var access_token = token["access_token"].ToString();
GraphServiceClient _graphServiceClient = new GraphServiceClient(
new DelegateAuthenticationProvider((request) =>
{
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", access_token);
return Task.FromResult(0);
}));
//Get user to test if calling GraphApi is successfull
//THIS WORKS FOR BOTH GRANT TYPES
var user = await _graphServiceClient.Me
.Request()
.GetAsync();
//Create printJob
var printJob = new PrintJob { Configuration = new PrintJobConfiguration { Copies = 1, } };
//THIS ONLY WORKS FOR authorization_code WORKFLOW
var printJobResponse = await _graphServiceClient.Print.Printers[printerId].Jobs
.Request()
.AddAsync(printJob);
}