Loopback-passport-component Allow single page application Login via Facebook - passport.js

I have been using loopback-component-passport with facebook login flow. As I'm moving to a single page app, I'm doing the facebook login using the FB sdk as described here: https://developers.facebook.com/docs/facebook-login/web
{
"facebook": {
"provider": "facebook",
"module": "passport-facebook",
"clientID": "<id>",
"clientSecret": "<secret>",
"callbackURL": "/auth/facebook/callback",
"authPath": "/auth/facebook",
"callbackPath": "/auth/facebook/callback",
"successRedirect": "/auth/account",
"failureRedirect": "/login",
"scope": [
"email"
],
"failureFlash": true
}
}
I'm able to retrieve the FB access token with the FB sdk, and sending the response.authResponse.accessToken value to GET http://localhost:3000/auth/facebook/callback?access_token=<token from FB sdk response> but I get an html response.
Am I doing something wrong or loopback does not support this feature?

For that use case, where you get the access token on the client, I think the passport-facebook-token module works better.
I've just been dealing with facebook oAuth, and I found that the best solution. You avoid the oAuth redirections, while still taking advantage of passport for the token validation and permanent session handling.

Related

Changing Azure AD Authority from /tenantID to /common causes 401

I have a Blazor WASM Azure static web app that communicates with an Azure AD protected API running on ASP.NET Core. I had setup Microsoft Account and one-time passcode IDPs.
I could sign in and call protected endpoints on my API - only when signed in - until I had my first Microsoft Account that wasn't in the tenant. They got AADSTS50020. The only cause that applied to me was cause 2 (used the wrong endpoint), so I changed my authority from https://login.microsoftonline.com/<YourTenantNameOrID> to https://login.microsoftonline.com/common according to that help page and this documentation.
Now every user can sign but we all get 401 unauthorized on protected endpoints.
The WWW-Authenticate header is set to Bearer error="invalid_token", error_description="The signature is invalid".
I obviously haven't "tried everything" if one simple change causes everything to break, but I've pored over documentation these past couple days to no avail.
Notes:
The one-time passcode sign-in option went away, and my main MS account is never auto-suggested even though I use it every time.
My tokens "look" fine, the aud is the API client id and the 1 necessary scope is present in scp.
API manifest
...
"oauth2AllowIdTokenImplicitFlow": true,
"oauth2AllowImplicitFlow": false,
...
"oauth2Permissions": [
{
"adminConsentDescription": "Allows the app to access the web API on behalf of the signed-in user",
"adminConsentDisplayName": "Access the API on behalf of a user",
"id": "<access_as_user scope id>",
"isEnabled": true,
"lang": null,
"origin": "Application",
"type": "User",
"userConsentDescription": "Allows this app to access the web API on your behalf",
"userConsentDisplayName": "Access the API on your behalf",
"value": "access_as_user"
}
],
...
"signInAudience": "AzureADandPersonalMicrosoftAccount",
...
Client manifest
...
"oauth2AllowIdTokenImplicitFlow": true,
"oauth2AllowImplicitFlow": true,
...
"requiredResourceAccess": [
...
{
"resourceAppId": "<api client id>",
"resourceAccess": [
{
"id": "<access_as_user scope id>",
"type": "Scope"
}
]
}
],
...
"signInAudience": "AzureADandPersonalMicrosoftAccount",
...
I can provide additional information, such as configuration code, but I didn't want to start out making the question too long.
Well, the rule of finding the answer shortly after posting on a help board relative to the time spent searching for the answer before posting on the help board reigns supreme.
For anyone who has the same question, my TenantId configuration on my API was set to my actual tenant id. Even if your client requests a token from the common endpoint, your API needs tenant set to common too.
See more:
https://learn.microsoft.com/en-us/azure/active-directory/develop/scenario-protected-web-api-app-configuration

Microsoft.Identity Platform login loop

I have been playing with Microsoft.Identity platform and trying to get it to work with the basic templates in aspnetcore 6.0, but I get stuck in an infinite login loop.
I am using projects created from the templates for web app and web api (using these commands "dotnet new webapi --force --auth IndividualB2C" and "dotnet new webapp --force --auth IndividualB2C") and then updated the appsettings in both to connect to my Azure B2C tenant.
WEB APP
"AzureAdB2C": {
"CallbackPath": "/signin-oidc",
"ClientId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"ClientSecret": "xxxxx",
"Domain": "xxxx.onmicrosoft.com",
"EditProfilePolicyId": "B2C_1_EditProfile",
"Instance": "https://xxxx.b2clogin.com/",
"SignedOutCallbackPath": "/signout/B2C_1_susi",
"SignUpSignInPolicyId": "B2C_1_SUSI"
},
"DownstreamApi": {
"BaseUrl": "https://localhost:7208/",
"Scopes": "https://xxxx.onmicrosoft.com/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/user.impersonation"
}
WEB API
"AzureAdB2C": {
"ClientId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"Domain": "xxxx.onmicrosoft.com",
"Instance": "https://xxxx.b2clogin.com/",
"Scopes": "https://xxxx.onmicrosoft.com/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/user.impersonation"
"SignUpSignInPolicyId": "B2C_1_SUSI"
}
After making these changes, I can run the applications and the Web App will attempt to login in through my social accounts then go into an infinite loop redirecting between the login server and the app redirect Url.
I do get a log message that MicrosoftIdentityWebChallengeUserException was thrown (presumably because I need to consent to the scopes). My understanding is that the [AuthorizeForScopes(ScopeKeySection = "DownstreamApi:Scopes")] attribute on the Razor page should handle this consent workflow for me, but it doesn't seem to be doing that.
Is there something additional I need to do in configuring these sample applications or a way to trap the WebChallenge exception (and if so, how do I issue the challenge back to the user)?
I feel like I am missing something obvious here to get this to work, but I cannot seem to find it. Can anyone provide some guidance to get this to work?
Please check if this can narrow down the issue:
Please clear cookies and try again.
AuthorizeForScopes attribute needs the exact scopes in that method. Any incorrect scopes there will result in MsalUiRequiredException .
Try hardcoding the parameters to whatever scopes are required :
[AuthorizeForScopes(Scopes = new[] { "User.impersonation”})]
Try using IExceptionFilter
And add filter in Startup.cs as follows:
services.AddMvc(options =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
options.Filters.Add(new AuthorizeForScopesAttribute(new string[] { Scopes:[] }));
})
Please checkout this SO reference
Reference:
active-directory-aspnetcore issues | github

How to create microsoft app password using API?

I'm able to create app id using Graph API but app secret/password is not generated with it. I need a way to generate/set a password using APIs.
Am I missing something?
You could create the password via Azure AD Graph API, you can test it in the AAD Graph Explorer.
My test sample:
Request URL:
PATCH https://graph.windows.net/{tenant id}/applications/{application object id}?api-version=1.6
Request body:
{
"passwordCredentials": [{
"endDate": "2020-08-12T02:54:44.2530506Z",
"keyId": "77fe4bf5-5d04-4a62-abc2-f064a9213d3f",
"startDate": "2019-08-12T02:54:44.2530506Z",
"customKeyIdentifier": "dGVzdA==",
"value": "XnkNIsT+cScOYeYJayQ4WNmp9tgAqw5z773uI9WQtAw="
}]
}
For more details about the request body, refer to this link - PasswordCredential.
Note: In the AAD Graph Explorer, when you send the request, the progress bar will never finish, but actually it works, you could check the result in the portal -> Azure Active Directory after a while.
Besides, there is also a Beta api in Microsoft Graph - Update application, I have not tested it, so I am not sure if it works. It is a Beta version, even if it works, I don't recommend you to use it in the production environment.
Are you following the correct API link?
Create User
It is easy to create Azure AD users using the Microsoft Graph REST. Here is a code sample for your reference:
POST https://graph.microsoft.com/v1.0/users
Authorization: Bearer {token}
Content-type: application/json
{
"accountEnabled": true,
"displayName": "Sajee",
"mailNickname": "Sinna",
"userPrincipalName": "upn-value#tenant-value.onmicrosoft.com",
"passwordProfile" : {
"forceChangePasswordNextSignIn": true,
"password": "password-value"
}
}

Refresh JWT tokens on each request

I'm setting up a document esigning process using Docusign. Since we have multiple associations, We have setup multiple accounts (around 20 APIAccountID under one organization (or you can say as one INTEGRATOR_KEY_ID)) one for each association. Can someone please let me know on how do we switch to different APIAccountID based on the request we get. Also, is it the right way to create a new DocuSignConnection every time when we get the request for different association ?
Your integration should use just one INTEGRATOR_KEY for the entire integration. When using one of the DocuSign OAuth flows such as JWT as you mention.
After the user grants access by providing their credentials and clicking Accept an access token will be sent back to your app (at the redirect URI you specify on your integrator key).
You then use that access token to call the User Info API which will return account ID for that given user.
User Info API
Request:
Authorization: Bearer eyJ0eX...MrhIddzBAQ
GET https://account-d.docusign.com/oauth/userinfo
Response:
{
"sub": "4799e5e9-1559-4915-9862-cf4713bbcacc",
"name": "Susan Smart",
"given_name": "Susan",
"family_name": "Smart",
"created": "2015-08-13T22:03:03.45",
"email": "susan.smart#example.com",
"accounts": [
{
"account_id": "a4ec37d6-04aa-4f37-86c2-143885c220e1",
"is_default": true,
"account_name": "Susan Smart",
"base_uri": "https://domain.example.com",
"organization": {
"organization_id": "9c5fb8e1-b0bf-4970-8e0e-054ff8a249bf",
"links": [
{
"rel": "self",
"href": "https://account.domain.example.com/organizations/9c5fb8e1-b0bf-4970-8e0e-054ff8a249bf"
}
]
}
}
]
}
You have one application which sends signing requests on behalf of multiple associations (organizations)?
As Ergin says, your application will have one integration key which will be used for all associations.
When a human logs into you app using OAuth Auth Code Grant, your app receives an access token. You can use that access token to look up the user's account and site (API URL).
Your application can make sending requests for any number of people and their associations. Each API request includes the user's individual access token, their account_id, and uses the site data to create the URL.
HTH.

chrome.identity and YouTube v3 API?

I was wondering if YouTube's v3 API and the OAuth2 support provided via chrome.identity played nicely together?
I can't seem to figure it out. Looking at: https://developers.google.com/youtube/v3/code_samples/javascript they seem to take a CLIENT_ID and scope, much like I am passing into my manifest.json.
Is there anything I can do with my OAuth2 identity token? Or do I have to go completely through YouTube's authorization process?
Update: I can fetch data using YouTube's way now, but not using the way I wanted..
gapi.auth.authorize({
client_id: '{CLIENT ID}.apps.googleusercontent.com',
scope: 'https://www.googleapis.com/auth/youtube',
// Set to false on first run to get pop-up interactivity
immediate: true
}, function (authResult) {
//console.log("Auth Result:", authResult);
gapi.client.load('youtube', 'v3', function () {
var request = gapi.client.youtube.channels.list({
mine: true,
part: 'contentDetails'
});
request.execute(function(response) {
console.log("response:", response);
});
});
});
My manifest.json has:
"oauth2": {
"client_id": "{CLIENT ID}.apps.googleusercontent.com",
"scopes": [
"https://www.googleapis.com/auth/youtube",
"https://www.googleapis.com/auth/youtube.readonly",
"https://www.googleapis.com/auth/youtube.upload",
"https://www.googleapis.com/auth/youtubepartner"
]
},
"permissions": [
"identity"
}
}
OAuth2 via the Google Javascript API is a separate process than the chrome.identity API. The identity API uses the extension id to generate a unique access token.
You have to choose one process over the other, their access tokens won't work with each other.
I'm currently using the JavaScript OAuth2 with the Analytics service because the chrome.identity process requires submitting your extension to the Chrome web store. The downside to the JavaScript process is it requires me to generate the login flow for users.

Resources