Dotnet core Handle multiple policy claims in JWT token - .net-core

Is there any other way available to handle multiple claims in single JWT token?
One approach is to pass only limited data to token and fetch permissions form database on each request
In-memory caching of permissions instead of database which saves database journey for every request
Sample token with multiple claims :
{
"Name": "user",
"Email": "user#email.com",
"UserID": "3e7849dc-2415-a37d-995f42031c70",
"SubscriberID": "886774eb-4f11-b89a-699a5d47d783",
"IsCompanyAdmin": "True",
"Role": "User",
"AppCodes": "App_6114f600958d18001fa86",
"Permission": [
"Permissions.Role.List",
"Permissions.Role.Edit",
"Permissions.Role.Create",
"Permissions.ControlFile.List",
"Permissions.ControlFile.Edit",
"Permissions.ControlFile.Create",
"Permissions.Criteria.Edit",
"Permissions.Criteria.Create",
"Permissions.OHC.List",
"Permissions.OHC.Edit",
"Permissions.OHC.Create",
"Permissions.StageGate.List",
"Permissions.StageGate.Edit",
"Permissions.StageGate.Create",
"Permissions.IMM.List",
"Permissions.IMM.Edit",
"Permissions.IMM.Create",
"Permissions.Action.List",
"Permissions.Action.Edit",
"Permissions.Action.Create",
"Permissions.Risk.List",
"Permissions.Risk.Edit",
"Permissions.Risk.Create",
"Permissions.Criteria.List",
"Permissions.Country.List",
"Permissions.City.List",
"Permissions.City.Edit",
"Permissions.City.Create",
"Permissions.County.List",
"Permissions.County.Edit",
"Permissions.User.Edit",
"Permissions.User.List",
"Permissions.User.Create",
"Permissions.Project.List",
"Permissions.Project.UserAccess"
],
"Menu": [
"CM002",
"CM002-1",
"CM002-2",
"CM002-3",
"CM001",
"CM002-1-1",
"CM002-1-2",
"CM002-2-1",
"CM002-2-2",
"CM002-2-3",
"CM002-2-4",
"CM002-2-5",
"CM002-2-6",
"CM002-3-1",
"CM002-3-2",
"CM002-3-3",
"CM003",
"CM004",
"CM006",
"CM007",
"CM008"
],
"exp": 1661431608,
"iss": "http://localhost:20028",
"aud": "http://localhost:20028"
}

Related

403 errors with keycloak API

I'm trying to use the Keycloak API (in node via keycloak-admin library) but I systematically get error 403.
I get successfully an access token via the library; by calling /auth/realms/master/protocol/openid-connect/token (on master realm) .
When I look inside my token, I seem to have the correct roles to be able to query the users :
{ "jti": "xx-..", "exp": 1585561478, "nbf": 0, "iat": 1585561418, "iss": "https://auth-mycompany.com/auth/realms/master", "aud": "mycompany-realm", "sub": "xx-..", "typ": "Bearer", "azp": "admin-cli", "auth_time": 0, "session_state": "xx-..", "acr": "1", "resource_access": { "mycompany-realm": { "roles": [ "view-users", "query-groups", "query-users" ] } }, "scope": "email profile", "email_verified": true, "name": "myname", "preferred_username": "myname", "given_name": "my name", "email": "myemail#mycompany.com" }
However , when I do a GET on https://auth-mycompany.com/auth/admin/realms/master/users or https://auth-mycompany.com/auth/admin/realms/mycompany/users ; I get 403 errors.
Maybe it's linked with the "aud" of my token ? Why do I get a token with "aud": "mycompany-realm" when I query master realm ?
Thanks for any help.
I eventually realize that this is due to the fact that I have implemented Port Restriction for admin endpoints. As described in the documentation, all endpoints starting with /auth/admin get a 403 response. Instead, these endpoints are accessible via another port (for example 9991) which is not accessible over the internet.
What I did to fix my issue : because both my Nodejs service and my keycloak server are running on the same kubernetes cluster, I change the authUrl of my keycloak server with its service name http://servicename.namespace.svc.cluster.local:9991/auth

How can I retrieve a RingCentral call recording from a monitored incoming call?

I'm monitoring incoming calls on RingCentral by listening for the Call Session Notifications (CSN) telephony/sessions event filter:
/restapi/v1.0/account/~/extension/~/telephony/sessions
From this, I will receive events like the following. The recordings property will appear to indicate a recording is available. How can I retrieve this recording?
{
"uuid":"12345678901234567890",
"event":"/restapi/v1.0/account/11111111/extension/22222222/telephony/sessions",
"timestamp":"2019-03-08T22:30:40.059Z",
"subscriptionId":"11112222-3333-4444-5555-666677778888",
"ownerId":"33333333",
"body":{
"sequence":7,
"sessionId":"1234567890",
"telephonySessionId":"1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
"serverId":"10.11.12.13.TAM",
"eventTime":"2019-03-08T22:30:39.938Z",
"parties":[
{
"accountId":"11111111",
"extensionId":"22222222",
"id":"cs12345678901234567890-2",
"direction":"Inbound",
"to":{
"phoneNumber":"+16505550100",
"name":"Jane Doe",
"extensionId":"22222222"
},
"from":{
"phoneNumber":"+14155550100",
"name":"John Smith"
},
"recordings":[
{
"id":"44444444",
"active":false
}
],
"status":{
"code":"Answered",
"rcc":false
},
"missedCall":false,
"standAlone":false,
"muted":false
}
],
"origin":{
"type":"Call"
}
}
}
There are two ways to retrieve the recording using information in the Call Session Notification (CSN) event, specifically the recordings[0].id property and the sessionID property.
retrieving a full media URL by calling the call-log endpoint with the sessionId property
manually creating recording media URL using the recordings[0].id property.
Note 1: While the call is ongoing, the recording will not be available for retrieval, even when the recording id is present in the Call Session Notification event. The recording will be available to be retrieved shortly after the call concludes.
Note 2: Call recordings can be in MP3 or WAV format determined by the company. To distinguish check the response Content-Type header for the MIME type when retrieving the recording media file.
1) Retrieving Full Medial URL via Call Log API
Making an intermediate API call to the call-log API has the dual benefits of being the official approach for receiving a media URL an providing more metadata for the call. In this approach, the recording.id in the call-log record will match the recordings[0].id property in the Call Session Notification event.
Both the company account and user extension call-log APIs can be called with the sessionId parameter from the event as shown:
GET /restapi/v1.0/account/~/call-log?sessionId={sessionId}
GET /restapi/v1.0/account/~/extension/~/call-log?sessionId={sessionId}
In this example, the sessionId is 1234567890 so you would have a Company Call Log API URL as follows
GET /restapi/v1.0/account/~/call-log?sessionId=1234567890
The response object will have a recording property that provides hypermedia links to get the media file. The file can be WAV or MP3 format which is communicated in the response Content-Type header.
{
"uri": "https://platform.ringcentral.com/restapi/v1.0/account/11111111/extension/22222222/call-log?view=Simple&sessionId=1234567890&page=1&perPage=100",
"records": [
{
"uri": "https://platform.ringcentral.com/restapi/v1.0/account/11111111/extension/22222222/call-log/1234567890ABCDEFGabcdefgh?view=Simple",
"id": "1234567890ABCDEFGabcdefgh",
"sessionId": "1234567890",
"startTime": "2019-03-08T22:30:29.505Z",
"duration": 35,
"type": "Voice",
"direction": "Inbound",
"action": "Phone Call",
"result": "Accepted",
"to": {
"phoneNumber": "+16505550100",
"name": "Jane Doe"
},
"from": {
"phoneNumber": "+14155550100",
"name": "John Smith",
"location": "San Francisco, CA"
},
"recording": {
"uri": "https://platform.ringcentral.com/restapi/v1.0/account/11111111/recording/44444444",
"id": "44444444",
"type": "OnDemand",
"contentUri": "https://media.ringcentral.com/restapi/v1.0/account/111111111/recording/44444444/content"
},
"extension": {
"uri": "https://platform.ringcentral.com/restapi/v1.0/account/111111111/extension/22222222",
"id": 22222222
},
"reason": "Accepted",
"reasonDescription": "The call connected to and was accepted by this number."
}
],
"paging": {
"page": 1,
"perPage": 100,
"pageStart": 0,
"pageEnd": 0
},
"navigation": {
"firstPage": {
"uri": "https://platform.ringcentral.com/restapi/v1.0/account/11111111/extension/22222222/call-log?view=Simple&sessionId=1234567890&page=1&perPage=100"
},
"lastPage": {
"uri": "https://platform.ringcentral.com/restapi/v1.0/account/11111111/extension/22222222/call-log?view=Simple&sessionId=1234567890&page=1&perPage=100"
}
}
}
2) Manually Creating Media URL
You can call the Recording API endpoint and retrieve the media directly by manually constructing the recording URL as follows:
https://media.ringcentral.com/restapi/v1.0/account/{accountId}/recording/{recordingId}/content
In this example, the accountId is 11111111 and the recordingId is 44444444 for the following:
https://media.ringcentral.com/restapi/v1.0/account/11111111/recording/44444444/content
The accountId in the URL path can be set to the currently authorized user's account using ~. Alternately, it can be set explicitly by extracting the accountId from the event property or using the accountId property in the relevant party object. Using ~ is the recommended way to set accountId.
Note: This this approach can be quick, it may be error prone as RingCentral has changed the media hostname once in the past. While there are no anticipated, future changes, calling the call-log API and retrieving the full media URL from the response is the safer and recommended approach. See below for this approach. This is only included as some people will try this and potentially run into issues later.
3) Hybrid Approach
The first approach of calling the call-log end point is the recommended approach, however, it involves an extra API call and most of the time the second approach should work fine.
A hybrid approach is to construct the URL as in approach 2 and then fall back to approach 1 if approach 2 returns a 404 or other error.

Firebase Admin SDK : Verifying ID tokens from the REST API

I'm trying to verify Id tokens received by signing in with the REST API for authentication by using the verifyIdToken(idToken) method in the Admin SDK but instead of getting the decoded token I get the error:
Firebase ID token has incorrect "iss" (issuer) claim. Expected "https://securetoken.google.com/"" but got "https://identitytoolkit.google.com/". Make sure the ID token comes from the same Firebase project as the service account used to authenticate this SDK. See https://firebase.google.com/docs/auth/admin/verify-id-tokens for details on how to retrieve an ID token.
As I said above I'm getting my token from the REST API, so I was expecting this to work.
The response I get from the API is this:
{
"kind": "identitytoolkit#VerifyPasswordResponse",
"localId": "pu0yjIc8tnR85X2gERdtLx684DK2",
"email": "test#test.com",
"displayName": "",
"idToken": "<token-id>",
"registered": true
}
Is this considered a custom token? if so, how can I verify it?
As of Sep 2018, the issuer of the ID Token returned by REST API seems to be changed from https://identitytoolkit.google.com/ to https://securetoken.google.com/. And I can successfully verify this id token in firebase admin SDK.
[Edit]: The firebase admin SDK still fails to verify the Facebook ID Token returned by identitytoolkit's verifyAssertion REST API.
According to Google Developer
Calling the tokeninfo endpoint
An easy way to validate an ID token for debugging and low-volume use
is to use the tokeninfo endpoint. Calling this endpoint involves an
additional network request that does most of the validation for you,
but introduces some latency and the potential for network errors.
To validate an ID token using the tokeninfo endpoint, make an HTTPS
POST or GET request to the endpoint, and pass your ID token in the
id_token parameter. For example, to validate the token "XYZ123", make
the following GET request:
https://www.googleapis.com/oauth2/v3/tokeninfo?id_token=XYZ123
{
// These six fields are included in all Google ID Tokens.
"iss": "https://accounts.google.com",
"sub": "110169484474386276334",
"azp": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com",
"aud": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com",
"iat": "1433978353",
"exp": "1433981953",
// These seven fields are only included when the user has granted the "profile" and
// "email" OAuth scopes to the application.
"email": "testuser#gmail.com",
"email_verified": "true",
"name" : "Test User",
"picture": "https://lh4.googleusercontent.com/-kYgzyAWpZzJ/ABCDEFGHI/AAAJKLMNOP/tIXL9Ir44LE/s99-c/photo.jpg",
"given_name": "Test",
"family_name": "User",
"locale": "en"
}

Triggering smart campaign and getting 603

I am trying to use Marketo smart campaign to send email data.
What I do is:
1) get or create Lead with addresse email
2) trigger smart campaign I've created with this lead_id and a couple of tokens I created on the folder containing the campaign.
That is, I am sending POST to https://.mktorest.com/rest/v1/campaigns/5826/trigger.json?access_token= with body
{
"input": {
"leads": [
{
"id": 2034349
}
],
"tokens": [
{
"name": "{{my.subject}}",
"value": "subj"
},
{
"name": "{{my.message}}",
"value": "the text"
}
]
}
}
And I get the response:
{u'errors': [{u'message': u'Access denied', u'code': u'603'}], u'requestId': u'c8f5#14c79fae723', u'success': False}
I was trying token names without "{{" and "}}", without "my." - the same result. The campaign exist and has this ID.
What's wrong here?
The role of the Marketo API user that you're using needs the "Execute Campaign" permission, and your current user is probably missing that permission. Unfortunately you can't edit the existing role. You'll need to create a new role, check that permission, and possibly also create a new API User.

How to "Add guest" to event via google calendar API?

could you please give me a hint on how to share a single event via google calendar api?
That is I'd like to invite other users to see the event programmatically without sharing the whole calendar. To mimic the "Add guests" UI action
As Claudio mentioned, you need to use the Google Calendar Advanced API for this.
You'll want to use a patch because you don't want to replace all the other data on the calendar invite. However, even in the case of patch, since the attendees lives in an array, if you attempt to pass a patch such as this:
{
attendees: [ { email: "new#example.com"} ]
}
... it'll replace all old invitees (i.e. it'll remove anyone that was on the invite before you called patch). To fix this, you must first get the current invitees, add a new person to the array, and then send a patch.
You can see a detailed example of this in this answer which also explains how to use Google Apps Scripting to ensure an email is sent to the user when adding them to a calendar event (see the addGuestAndSendEmail() method in that post).
You can use the API to add people to the attendees collection:
https://developers.google.com/google-apps/calendar/v3/reference/events/update
refer the following request.
method: POST
endpoint: https://www.googleapis.com/calendar/v3/calendars/primary/events?sendUpdates=all
here, sendUpdates means when you add any guest so he would get an invitation mail used based on scenario.
Input Json:
{
"kind": "calendar#event",
"etag": "etag",
"status": "confirmed",
"summary": "JayKara",
"description": "eqwbdjhwhhwhhwrhjehrhejhfj",
"location": "America",
"creator": {
"email": "#mail.com",
"self": true
},
"organizer": {
"email": "#mail.com",
"self": true
},
"start": {
"date": "2019-12-23"
},
"end": {
"date": "2019-12-24"
},
"originalStartTime": {
"date": "2019-12-24"
},
"visibility": "public",
"attendees": [
{
"email": "****#mail.com" //this guys are the guest
}
]
}.
After that there is no patch method required your guest guys will receive an invitation whenever update event
Cheers!

Resources