Angularfire/Firebase Facebook Authentication - A Better Profile Picture [duplicate] - angularjs

I am using firebase facebook simple login.
Is there any way I can use it conjunction with facebook js graph api?
Let say, calling FB.api('xxx', function(){}) ?

Facebook via Firebase Simple Login returns the Facebook access token as part of the payload. You could then use this directly with the Facebook Graph API and their JavaScript SDK:
var ref = new Firebase(URL);
var auth = new FirebaseSimpleLogin(ref, function(error, user) {
if (user) {
var facebookToken = user.accessToken; // <<-- here it is
}
});
// Note: Attach this to a click event to permit the pop-up to be shown
auth.login('facebook');
As you noted, Singly is another great approach that abstracts some of the effort of talking to Facebook, but shouldn't be necessary if your use case is fairly straightforward.
UPDATE
Firebase Simple Login now supports authenticating a user with an existing Facebook access token, meaning that you can easily use the Facebook JS SDK in combination with Firebase Simple Login without asking your users to authenticate twice.
For example, once you have a valid Facebook access token using the Facebook JS SDK:
var ref = new Firebase(...);
var auth = new FirebaseSimpleLogin(ref, function(error, user) { ... });
auth.login('facebook', { access_token: '<ACCESS_TOKEN>' });
See the access_token option at https://www.firebase.com/docs/security/simple-login-facebook.html for more information.

Related

ASP.NET 6 WebAPI Authentication with SSO

I have an ASP.NET 6.0 Web API project. I would like to add authentication and authorization to it, but it must use SSO via Azure.
We already have a SPA application that does this, it uses the Angular MSAL library to redirect the user to an SSO Login page, then returns to the SPA with an access token. The access token is then added to the header of each request to the Web API, which uses it to enforce authentication.
Now we want to share our web API with other teams within our organization, and we would like to have that login process just be another API call, rather than a web page.
Conceptually, a client would hit the /login endpoint of our API, passing in a userID and password. The web API would then get an access token from Azure, then return it as the payload of the login request. It's then up to the client to add that token to subsequent request headers.
I have done this with regular ASP.NET Identity, where all of the user and role data is stored in a SQL database, but since our organization uses SSO via Azure Active Directory, we would rather use that.
I have researched this topic online, and so far all of the examples I have seen use a separate SPA, just like we already have. But as this is a web api, not a front-end, we need to have an API method that does this instead.
Is this even possible? I know Microsoft would rather not have user credentials flow through our own web server, where a dishonest programmer might store them for later misuse. I understand that. But I'm not sure there's a way around this.
Thanks.
I believe you are looking for the Resource Owner Password (ROP) flow. You can use IdentityModel.OidcClient to implement it.
Sample code:
public class Program
{
static async Task Main()
{
// call this in your /login endpoint and return the access token to the client
var response = await RequestTokenAsync("bob", "bob");
if (!response.IsError)
{
var accessToken = response.AccessToken;
Console.WriteLine(accessToken);
}
}
static async Task<TokenResponse> RequestTokenAsync(string userName, string password)
{
var client = new HttpClient();
var disco = await client.GetDiscoveryDocumentAsync(Constants.Authority);
if (disco.IsError) throw new Exception(disco.Error);
var response = await client.RequestPasswordTokenAsync(new PasswordTokenRequest
{
Address = disco.TokenEndpoint,
ClientId = "roclient",
ClientSecret = "secret",
UserName = userName,
Password = password,
Scope = "resource1.scope1 resource2.scope1",
Parameters =
{
{ "acr_values", "tenant:custom_account_store1 foo bar quux" }
}
});
if (response.IsError) throw new Exception(response.Error);
return response;
}
}
Sample taken from IdentityServer4 repository where you can find more ROP flow client examples.
I would recommend that you don't go with this implementation and instead have all clients obtain their access tokens directly from Azure AD like you did with your Angular SPA.

IdentityServer4 and SPA Applications and New User Registration

What is the correct approach to handle new user registration for a SPA (Angular) application? I am using IdentityServer 4 for authentication (Code Flow) and authorization to my APIs and that is working well. However, I am unsure where should new user registration takes place, especially I want the new user to be automatically logged in after registration, in other words, I would not want them to have to go to a log-screen after registration. Should the registration be handle in the SPA application or in a special view in IdentityServer? In either case, how do I get the JWT token afterward to allow access to my APIs?
Thanks in advance.
You'll want the registration to be handled in the Identity Server project. You can add two new methods to the AccountController.cs class that will be similar to the Login* methods in the class, one for loading the page and another for handling the registration input.
Assuming that you are using Microsoft Identity for managing user accounts you can have your registration endpoint take the info from the registration page, create the Identity in the database, then call the same login method that the login endpoint calls. Something along the lines of this
// Do model validation, verify the user doesn't already exist, etc...
...
var createUser = await _userManager.CreateAsync(new ApplicationUser
{
Email = model.UserName,
NormalizedEmail = model.UserName,
UserName = model.UserName,
FirstName = model.FirstName,
LastName = model.LastName
}, model.Password);
var user = await _userManager.FindByEmailAsync(model.UserName);
if (createUser.Succeeded)
{
// Add roles to the user
await _userManager.AddToRoleAsync(user, "Customer");
var result = await _signInManager.PasswordSignInAsync(model.UserName, model.Password, false, lockoutOnFailure: false);
...
// You'll want to redirect back to the client site to complete the login process

List Cognito Users in React web app

This is my first cognito project. I am making an admin page which will have read only access to all Cognito Users and their attributes. I have looked through aws-amplify and aws-amplify-react and cannot figure out how to get them to access ListUsers function or something similar. Does anyone have an example of how this is done in React.
I am considering saving User data in a separate Dynamodb table which I can easily access. I am also wondering which is cheaper? Read/Writing User Attributes in Cognito or in Dynamodb? I can only find documentation on number of active users in Cognito and nothing on how often their attributes are read/wrote to.
I ran into a similar issue, but what I ended up doing was creating a lambda function for this and using the SDK to access this information. You could create an API endpoint through the mobilehub CLI and then the lambda it creates you can edit in your local express project under the desired get request of your choosing and put in the following:
var cognito = require('aws-sdk/clients/cognitoidentityserviceprovider');
app.get('/users', function(req, res) {
let params = {
UserPoolId: userPoolIdHere,
AttributesToGet: [
'COGNITO_ATTRIBUTE_NAME',
'COGNITO_ATTRIBUTE_NAME
];
};
cognito.listUsers(params, function(err, data) {
if(err) {
res.json(err);
} else {
res.json(data);
}
});
}

Using Firebase Auth to access the Google Calendar API

I am building a web application using AngularJS, Firebase (SDK v3) and Google Calendar API. I'm authenticating users using Google OAuth. My purpose is to be able to create calendar events from database nodes in Firebase. So far I've managed to request access to the calendar scope with:
_authProvider = new firebase.auth.GoogleAuthProvider();
// Get permission to manage Calendar
_authProvider.addScope("https://www.googleapis.com/auth/calendar");
_fbAuthObject.signInWithRedirect(_authProvider);
I'm authenticating with the redirect flow so the authentication redirect is available as:
_fbAuthObject.getRedirectResult()
.then(function _readToken(result) {
if (result.credential) {
_googleToken = result.credential.accessToken;
var authHeader = 'Bearer '+ _googleToken;
// Just a test call to the api, returns 200 OK
$http({
method: 'GET',
headers: {
'Authorization': authHeader
},
url: 'https://www.googleapis.com/calendar/v3/users/me/calendarList/primary'
})
.then(function success(response) {
console.log('Cal response', response);
},
function error(response) {
console.log('Error', response);
});
However, it seems like outside the initial login it's not possible to get the Google access token through the Firebase SDK. It seems only possible to access the Firebase JWT token, no use with the Calendar API. I could store the access token, but this wouldn't resolve the problems when refreshing the token, etc. Is there any way to get the current Google Access token with Firebase SDK and if not, what other solutions is there to the problem without having to authenticate the user twice?
UPDATE 1:
Seems like someone else has struggled with similar problems with Facebook authentication. On that question there was a link to the Firebase documentation stating that Firebase Authentication no longer persists the access token. So how can I handle token refreshes? Is there really no answer to this?
UPDATE 2:
So, I contacted Firebase Support with a feature request about this problem and they gave me the following answer:
Thanks for taking your time to write us.
I've got your point here, this is indeed a good suggestion. We're definitely aware that many users, such as yourself, would like OAuth feature that will access token upon refresh. We're exploring potential solutions, but I cannot guarantee if this will be available anytime soon. We'll keep your feedback in consideration moving forward though. Continuous improvement is very important for our community, so thanks for bringing this up!
Keep an eye out on our release notes for any further updates.
So It seems like the access tokens are not available through the Firebase SDK at the moment. I'm still trying to find a workaround, so if anyone has ideas about a valid solution I'd be glad to hear them. And of course, I'll be posting it here if I ever find a working solution myself.
I finally got around this problem by handling the authentication outside Firebase with the Google APIs JavaScript client. This solution requires including the Google auth client as documented here. Manually handling the Firebase sign-in flow is documented here.
gapi.auth2.getAuthInstance().signIn()
.then(function _firebaseSignIn(googleUser) {
var unsubscribe = firebase.auth().onAuthStateChanged(function(firebaseUser) {
unsubscribe();
// Check if we are already signed-in Firebase with the correct user.
if (!_isUserEqual(googleUser, firebaseUser)) {
// Build Firebase credential with the Google ID token.
var credential = firebase.auth.GoogleAuthProvider.credential(
googleUser.getAuthResponse().id_token);
// Sign in with credential from the Google user.
return firebase.auth().signInWithCredential(credential)
.then(function(result) {
// other stuff...
});
The _isUserEqual function:
function _isUserEqual(googleUser, firebaseUser) {
if (firebaseUser) {
var providerData = firebaseUser.providerData;
for (var i = 0; i < providerData.length; i++) {
if (providerData[i].providerId === firebase.auth.GoogleAuthProvider.PROVIDER_ID &&
providerData[i].uid === googleUser.getBasicProfile().getId()) {
// We don't need to reauth the Firebase connection.
return true;
}
}
}
return false;
}
Now I can reference the access token like this:
var user = gapi.auth2.getAuthInstance().currentUser.get();
return user.getAuthResponse().access_token;
This still isn't the ideal solution for me, but it works for now, and I'm able to authenticate to both Firebase and the Calendar API.

Satellizer: login using FB's access_token

I'm implementing a hybrid iOS web and native app. I'm using iOS native FB login capabilities, and sending the access_token from the native app to the web, which uses Satellizer.
The question is: can I avoid the FB permissions dialog and directly use the access_token to sign up the user and recover the JWT from the server, using the normal Satellizer flow?
Permission dialog is a must for every third party social login.
The user need to approve and to know what application he is going to use with that social network and what permissions he will give to that specific application.
I solved it doing Satellizer job of sending the access_token and storing it manually:
$http.post('/auth/facebook', {
token: receivediOSToken
}).then(function (response) {
$auth.setToken(response.data.token);
loginSuccess();
}, function () {
loginError();
});

Resources