The number of keys specified in the URI does not match number of key properties for the resource 'microsoft.graph.bookingAppointment - graph

We are trying to use Graph APIs for Bookings application. In fact, we are customizing
the C# code from the microsoft sample :
https://microsoft.github.io/bookings-samples/
We have the application registration and all the permissions configured in Azure.
Using the BookingsSampleNativeConsole, we are able to query the graphService.BookingBusinesses
as shown below.
var graphService = new GraphService(GraphService.ServiceRoot,
() => authenticationResult.CreateAuthorizationHeader());
Unfortunately none of the other entities gets populated. So we are using the following to query the appointments:
Uri appointUri = new Uri("https://graph.microsoft.com/beta/bookingBusinesses/{id}/appointments");
var appointParams = new UriOperationParameter[]
{
new UriOperationParameter("start", "2020-08-01T00:00:00Z"),
new UriOperationParameter("end", "2020-08-31T00:00:00Z")
};
var resp = graphService.Execute(appointUri, "GET", appointParams);
But this call returns :
An error occurred while processing this request. --->
Microsoft.OData.Client.DataServiceClientException:
{
"error":
{
"code": "BadRequest",
"message": "The number of keys specified in the URI does not match number of key properties for the resource 'microsoft.graph.bookingAppointment'."
}
}
Any idea what we are missing or wrong with appointParams ?
Thanks in advance.
(2)Graph APIs for Bookings has been in beta for quite sometime now. Any idea
when is the probable release date for version 1.0 ?
Ajit19

Related

Using ResourceOwnerPassword flow for .NET Core 3.1/IdentityModel 5.1

I am playing with the IdentityServer4. Part of that I am trying to build a client using IdentityModel 5.1.0 and trying to use following piece of code available here
// request token
var tokenClient = new TokenClient(disco.TokenEndpoint, "ro.client", "secret");
var tokenResponse = await tokenClient.RequestResourceOwnerPasswordAsync("alice", "password", "api1");
if (tokenResponse.IsError)
{
Console.WriteLine(tokenResponse.Error);
return;
}
Console.WriteLine(tokenResponse.Json);
Console.WriteLine("\n\n");
But this is giving me following error.
error CS1729: 'TokenClient' does not contain a constructor that takes 3 arguments
From the docs, it looks like that page is only applicable to Core 1.0. When I change the documentation to 3.1.0, I get
Sorry This pages does not exist yet
Does this mean that ResourceOwnerPassword flow is not supported for the .NET Core 3.1?
Ctrl + clicking on the method takes to to its signature, where you can find out the specific parameters that the method expects.
Browsing the repo, I've found this snippet on using the password credentials token request:
var response = await _client.RequestPasswordTokenAsync(new PasswordTokenRequest
{
ClientId = "client",
UserName = "user",
Password = "password",
Scope = "scope",
Resource = { "resource1", "resource2" }
});
another overload:
var response = await tokenClient.RequestPasswordTokenAsync(userName: "user", password: "password", scope: "scope");
Or see the actual method definition or another helper.
A useful tip: popular packages usually have a lot of tests. You can check them out to learn how to use the library.

FHIR JSON to XML decoding in BizTalk

I am just starting out with FHIR and with json so my question may not be well asked.
I have built a BizTalk pipeline component to convert FHIR-json to FHIR-xml using this library, https://github.com/ewoutkramer/fhir-net-api , based on an example i found here, http://soapfault.com/blog/2016/08/hl7-fhir-json-decoding-in-biztalk/
Here is a code snippet from the pipeline component. It's almost identical to the example.
//Read the json message
using (TextReader tr = new StreamReader(originalDataStream))
{
json = tr.ReadToEnd();
}
//Use FHIR-NET-API to create a FHIR resource from the json
Hl7.Fhir.Serialization.ResourceReader resourceReader = new Hl7.Fhir.Serialization.ResourceReader(FhirJsonParser.CreateFhirReader(json), ParserSettings.Default);
//Use FHIR-NET-API to serialize the resource to XML
byte[] resourceXmlBytes = Hl7.Fhir.Serialization.FhirSerializer.SerializeToXmlBytes(resourceReader.Deserialize());
The pipeline component is able to decode any single json FHIR message that starts with
{
"resourceType": "ImagingStudy",
but I get a parsing error on the messages that start like this,
{
"resourceType" : "Bundle",
"entry" : [{
"resource" : {
"resourceType" : "ImagingStudy",
or
{
"entry": [
{
"fullUrl": "http://fhirtest.uhn.ca/baseDstu2/ImagingStudy/EXexample",
"resource": {
"resourceType": "ImagingStudy",
Here are a couple of the errors I have got,
There was a failure executing the receive pipeline: "LALALA.Imaging.Pipelines.FHIRJasonDecoderRP, LALALA.Imaging.Pipelines, Version=1.0.0.0, Culture=neutral, PublicKeyToken=19bb8b5ea64396aa" Source: "FHIRJsonDecoder" Receive Port: "RP_LA_Test_FILE" URI: "D:\Projects\LALALA.Imaging\In\*.json" Reason: Data at the root level is invalid. Line 1, position 1.
OR
Reason: At line 1, pos 1: Cannot determine type of resource to create from json input data: no member resourceType was found
For my solution the ultimate goal is to to be able parse bundles of FHIR image study messages into single fhir xml messages that will then be mapped to HL7 ORU messages.
Any help with the issue above or suggestions on how to achieve my end goal using BizTalk would be greatly appreciated.
It's generally not necessary to call the ResourceReader directly, nevertheless I tried to reproduce your error like this:
var json = #"{
""resourceType"" : ""Bundle"",
""entry"" : [{
""resource"" : {
""resourceType"" : ""ImagingStudy""
}}]}";
// SHORT VERSION: var b = new FhirJsonParser().Parse<Bundle>(json);
var b = new
Hl7.Fhir.Serialization.ResourceReader(
FhirJsonParser.CreateFhirReader(json),
ParserSettings.Default).Deserialize();
Assert.IsNotNull(b);
Both work fine, however. Maybe something goes wrong while reading the stream?
You could also try reading directly from the stream:
var b = new FhirJsonParser().Parse<Bundle>(new
Newtonsoft.Json.JsonTextReader(stream));

Google OpenId Connect migration: getting the openid_id in ASP.NET app

I've gone through plenty of Google documentation and SO Q/A's but with no luck. I wonder if anyone has yet succesfully used the OpenId to OpenId Connect migration as advised by Google.
This is what we used to do:
IAuthenticationResponse response = _openid.GetResponse();
if (response != null) {
//omitted for brevity
} else {
IAuthenticationRequest req = _openid.CreateRequest("https://www.google.com/accounts/o8/id");
req.AddExtension(new ClaimsRequest
{
Country = DemandLevel.Request,
Email = DemandLevel.Request,
Gender = DemandLevel.Require,
PostalCode = DemandLevel.Require,
TimeZone = DemandLevel.Require
});
req.RedirectToProvider();
}
That was done using a version of DotNetOpenAuth that dates back a few years. Because Google has deprecated OpenId authentication we are trying to move over to OpenID Connect. The key question here is: can I somehow get my hands on the OpenId identifier (in the form of https://www.google.com/accounts/o8/id?id=xyz) using the latest version of DotNetOpenAuth library or by any other means?
I have tried the latest DotNetOpenAuth and I can get it to work but it gives me a new Id (this was expected). I have also tried the Javascript way by using this URL (line breaks for readibility):
https://accounts.google.com/o/oauth2/auth?
scope=openid%20profile%20email
&openid.realm=http://localhost/palkkac/
&client_id=//here is the client id I created in google developer console
&redirect_uri=http://localhost/palkkac/someaspxpagehere
&response_type=id_token%20token
I checked (using Fiddler) the realm value that we currently send using the old DotNetOpenAuth code and it is http://localhost/palkkac/. I've put the same realm in the url above. The redirect url starts with the realm value but it is not entirely the same.
When I redirect to a simple page that parses the id_token and decrypts it (using the https://www.googleapis.com/oauth2/v1/tokeninfo?id_token=zyx endpoint) I get this:
audience "client id is here"
email "mikkark#gmail.com"
expires_in 3597
issued_at //some numbers here
issued_to "client id is here"
issuer "accounts.google.com"
user_id "here is a sequence of numbers, my id in the OpenID Connect format that is"
verified_email true
So there is no sign of the openid_id field that you would expect to find here, though the whole structure of the message seems different from the Google docs, there is no field titled sub, for example. I wonder if I'm actually using the wrong endpoint, parameters or something?
What I have been reading is the migration guide: https://developers.google.com/accounts/docs/OpenID. I skipped step 2 because it seemed like an optional step. In step 3 the field openid_id is discussed and I would like to get that to work as a proof-of-concept first.
We registered the app on Google in order to create the client id etc. There are now also numerous allowed redirect url's as well as javascript origins listed in the Google dev console. Let me know if those might mess up the system and I'll post them here for review.
Side note: we are supposed to be moving our app behind a strictly firewalled environment where we would need to open ports in order to do this on the server side. Therefore, a client-side Javascript solution to access Google combined with HTTPS and redirecting the result to the server would be prefered (unless there are other issues that speak against this).
There are other resources on SO regarding this same issue, although all of these seem to use different libraries on the server side to do the job and nobody seems to have made any attempts at using Javascript:
Here (https://stackoverflow.com/questions/22842475/migrating-google-openid-to-openid-connect-openid-id-does-not-match) I think the problem was resolved by setting the realm to be the same as in the old OpenId2.0 flow. This does not seem to work in my case.
over here the openid_id field is also missing, but the problem here is more about how to request the id_token from Google using libraries other than DotNetOpenAuth.
and in here there seem to be similar problems getting Google to return the openid_id field.
You can use the GoogleAuthentication owin middleware.
app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions
{
SignInAsAuthenticationType = signAs,
AuthenticationType = "Google",
ClientId = "xxx.apps.googleusercontent.com",
ClientSecret = "xx",
CallbackPath = PathString.FromUriComponent("/oauth2callback"),
Provider = new GoogleOAuth2AuthenticationProvider
{
OnApplyRedirect = context =>
{
context.Response.Redirect(context.RedirectUri + "&openid.realm=https://mydomain.com/"); // DotNetOpenAuth by default add a trailing slash, it must be exactly the same as before
}
},
BackchannelHttpHandler = new MyWebRequestHandler()
}
Then, add a new class called MyWebRequestHandler:
public class MyWebRequestHandler : WebRequestHandler
{
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var httpResponse = await base.SendAsync(request, cancellationToken);
if (request.RequestUri == new Uri("https://www.googleapis.com/plus/v1/people/me")) return httpResponse;
var configuration = await OpenIdConnectConfigurationRetriever.GetAsync("https://accounts.google.com/.well-known/openid-configuration", cancellationToken); // read the configuration to get the signing tokens (todo should be cached or hard coded)
// google is unclear as the openid_id is not in the access_token but in the id_token
// as the middleware dot not expose the id_token we need to parse it again
var jwt = httpResponse.Content.ReadAsStringAsync().Result;
JObject response = JObject.Parse(jwt);
string idToken = response.Value<string>((object)"id_token");
JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();
try
{
SecurityToken token;
var claims = tokenHandler.ValidateToken(idToken, new TokenValidationParameters()
{
ValidAudience = "xxx.apps.googleusercontent.com",
ValidIssuer = "accounts.google.com",
IssuerSigningTokens = configuration.SigningTokens
}, out token);
var claim = claims.FindFirst("openid_id");
// claim.Value will contain the old openid identifier
if (claim != null) Debug.WriteLine(claim.Value);
}
catch (Exception ex)
{
Debug.WriteLine(ex.ToString());
}
return httpResponse;
}
}
If like me you found this not really straightforward, please help by upvoting this issue https://katanaproject.codeplex.com/workitem/359

What is the parameter name for basic authentication in meteor's http.post API?

I'm using HTTP.post in meteor and I need to send basic authentication with only a username to an external service. Where does this go and what would that look like?
I am only using it on the server side so I know it should look like the below code, but I'm not sure where to put the username and what to call it.
I've tried this.
var resultSet = HTTP.post("https://billy.balancedpayments.com/v1/customers", {
params: {"processor_uri": "/customers/customerURI"},
authentication: {"MYKEYHERE":""}
});
And this.
var resultSet = HTTP.post("https://billy.balancedpayments.com/v1/customers", {
params: {"authentication": "MYKEYHERE",
"processor_uri": "/customers/customerURI"}
});
And this.
var resultSet = HTTP.post("https://billy.balancedpayments.com/v1/customers", {
params: {"processor_uri": "/customers/customerURI"
},
headers: {'Authorization': 'MYKEYHERE'}
});
I get this error each time.
Error: failed [403] 403 Forbidden Access was denied to this resource.
Unauthorized: CustomerIndexView failed permission check
The plain auth : 'username:password' should do (from docs):
var resultSet = HTTP.post("https://billy.balancedpayments.com/v1/customers", {
params: {"processor_uri": "/customers/customerURI"},
auth: 'yourkey:'
});
As per the balanced payments documentation:
To authenticate with Balanced, you will need the API key secret provided from the dashboard. You have to use http basic access authentication. Your key has to be set as the username. A password is not required for simplicity.
So this means you leave the password blank, so its just your key followed by the colon :
Also you might want to consider using the balanced package for Meteor which does all the boilerplate for you.

Getting Google Oauth2 Token using dotnetopenauth

I'm having an issue retreiving the OAuth2 token for google using DotNetOpenAuth 4.2.0.13024.
I've got to the point where I can successfully make the authorization request to the google endpoint https://accounts.google.com/o/oauth2/auth
When the user clicks 'OK', google then calls my callback URL as expected with the appropriate "code" query string.
However, I am unable to exchange this code for a token, as my calls keep failing with "Protocol exception was unhandled" execption and "400 Bad request" as the inner exception. This is the code I am using to exchange the token
private static AuthorizationServerDescription authServerDescription = new AuthorizationServerDescription
{
TokenEndpoint = new Uri("https://accounts.google.com/o/oauth2/token"),
AuthorizationEndpoint = new Uri("https://accounts.google.com/o/oauth2/auth")
};
static GoogleContacts()
{
Client = new WebServerClient(authServerDescription, "{my_cliend_id}", "{me_secret_key}");
}
var authorization = Client.ProcessUserAuthorization(); // <- Exception is thrown here
if (authorization != null)
{
Authorization = authorization;
Response.Redirect(Request.Path); // get rid of the /?code= parameter
}
PS: it seems like a new version of DotNerOpenAuth has been released but, I am unable to get it because the zip download still points to the older version and Nuget keeps failing on me :(

Resources