Angular2 and symfony3 FOSOAuthServerBundle authorisation - symfony

I want to connect my angular2 frontend app with symfony backend. So I'm using FOSOAuthServerBundle (https://github.com/FriendsOfSymfony/FOSOAuthServerBundle) to authorize my frontend app, but I don't understand clearly how to implement this.
I tried "token" endpoint method, but there I had to send client_id and client_secret, from my angular2 app. And I think it's bad to store client_secret in public.
"Authorize" endpoint don't use client_secret, but is demanding login form, what is not good for my case.
I tried custom grant extension, but FOSOAuthServerBundle also requires to validate client with client_secret.
What is best practice authorize angular2 with symfony? It's ok to store client_secret in frontend? Or should I extend FOSOAuthServerBundle and remove client_secret checking?

You're correct about client_secret. It's not valid practice to publish secret key more widely.
Unfortunately at this moment FOSOAuthBundle is not suitable to your needs. This bundle focus only about backend OAuth clients. They have open issue on github to add support of public clients: https://github.com/FriendsOfSymfony/FOSOAuthServerBundle/issues/266
One thing to clarify regarding token & authorize endpoints - token and authorize endpoints have to be mixed in process of access to your resource. I suggest you to read whole RFC to understand process of authorization with OAuth: https://www.rfc-editor.org/rfc/rfc6749

Hacky solution: in src/Entity/OAuth2/Client.php you can overwrite the checkSecret method like this:
public function checkSecret($secret)
{
if (in_array("authorization_code", $this->getAllowedGrantTypes())) {
return true;
}
return parent::checkSecret($secret);
}

Related

Symfony JWT - Change the login way using symfony lexik JWT Authentication Bundle

In the Symfony Lexik JWT Authentication bundle, It is explained how to authenticate users using a table in the database.
In my case, My users aren't in the database but are in another application that I can access via API calls.
Also, to retrieve the users from this API, all I have to do is send a token associated with every user and get his information.
This token is well handled and is unique for each user.
How can I change the way LexikJWTAuthenticationBundle authenticate users using this API instead of the database.
And after this authentication, I want the JWT token to contain all the user information so I won't have to call this API each time a request is made to my application.
I made this diagram to explain my situation:
I tried from my side building a custom ApiUserProvider and an ApiUserAuthenticator but I am struggling to get this working.
Any help?
Here's described how to manually create JWTs for users: https://github.com/lexik/LexikJWTAuthenticationBundle/blob/2.x/Resources/doc/7-manual-token-creation.md you should be able to use that in your endpoint which authenticates the user, and return your own JWT.

IdentityServer4 Google sign callback doesn't include "IdentityConstants.ExternalScheme" cookie

I have an IdentityServer4 identity provider server. For the most part, I am using the template code from their repo. I am trying to add Google sign-in. I configured the GoogleSignIn in startup and added ClientId/ClientSecret.
When I don't configure the return URIs in the GCP project I get the following error from Google:
"The redirect URI in the request, https://localhost:44333/signin-google, does not match the ones authorized for the OAuth client. To update the authorized redirect URIs..."
When I add the URI
Then as soon as I call Challenge I immediately get a failed callback from Google.
[HttpGet]
public async Task<IActionResult> Callback()
{
var result = await HttpContext.AuthenticateAsync(IdentityConstants.ExternalScheme);
// Here, result.Succeeded is false
// Rest of the method...
}
What could be the problem?
If you have made it to the Callback method, then it sounds like Google auth has completed successfully. However, since the IdentityConstants.ExternalScheme cookie is not present, it sounds like you might have a little misconfiguration.
Once the Google authentication handler has completed, it will sign in using the auth scheme set in its SignInScheme property or the default sign-in scheme. It stores the claims from Google into a local auth method, such as a cookie.
What scheme is the Google authentication handler configured to use? If you're using the quickstarts, it may be using IdentityServerConstants.ExternalCookieAuthenticationScheme rather than ASP.NET Identity's IdentityConstants.ExternalScheme that you are looking for.

Handling logging into SPA application: getting user info, managing claims

Context:
I've implemented OpenIddict in my application, basing on GitHub readme. I currently use TokenEndpoint to log user in.
services.AddOpenIddict<ApplicationUser, UsersDbContext>().EnableTokenEndpoint("/api/Account/Login")
Although calling /api/Account/Info works and it returns token in response, I need to get some basic data about logged in user (username, email, account type). Response from token endpoint doesn't provide that.
I've found something like UserinfoEndpoint:
.EnableUserinfoEndpoint("/api/Account/Info")
But what I see after in http response is:
{
"sub": "ea2248b4-a[...]70757de60fd",
"iss": "http://localhost:59381/"
}
This should return me some Claims. As it doesn't return anything, I assume that no Identity Claims were created during token generation.
What I need to know in a nutshell:
Is using Token Endpoint correct way to log in user?
Do I need to generate Claims by myself?
Can I control Claims by myself and how?
How to make some Claims visible through UserInfoEndpoint?
Is using Token Endpoint correct way to log in user?
Yep.
Do I need to generate Claims by myself?
The userinfo endpoint simply exposes the tokens stored in the access token (which is something that may change in the future).
Can I control Claims by myself and how?
How to make some Claims visible through UserInfoEndpoint?
To allow the userinfo endpoint to return more claims, you'll have to request more scopes. Read http://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims for more information.
In a future version, we may allow you to return custom claims, but it's not currently supported.

Where to authenticate user in a SPA?

I have an Aurelia SPA that connects to a ASP.NET Core backend. I use Auth0 for authentication (using aurelia-auth, not the Auth0 Lock widget).
I currently log in with Auth0 directly, not using the SPA. This gives me issues because the Auth0 implementation in my API expects the id_token and not the access_token. This issue can be passed by telling aurelia-auth to use the id_token as access token. But this complicates further communication between Auth0 and the Aurelia app. Auth0 expects the access_token for user profile calls and such.
Should I authenticate via my own API instead? Or should I make two different fetch-clients in Aurelia? One for calling my API (using the id_token) and one for calling the Auth0 API (using the access_token).
I've written a number of blogs on the subject, and I'll link them below for further reading. My recommendation is to create a separate "authentication" root viewModel that is available to all users, distinct from your "app" root viewModel which is available to only logged in users.
main.js
import AuthService from 'AuthService';
export function configure(aurelia) {
aurelia.use
.standardConfiguration()
.developmentLogging();
// After starting the aurelia, we can request the AuthService directly
// from the DI container on the aurelia object. We can then set the
// correct root by querying the AuthService's isAuthenticated method.
aurelia.start().then(() => {
var auth = aurelia.container.get(AuthService);
let root = auth.isAuthenticated() ? 'app' : 'login';
aurelia.setRoot(root);
});
}
Further reading
Aurelia Authentication Best Practices, Multiple Shells
Aurelia Authentication Best Practices, Sessions
Sentry, an Aurelia Authentication Template

Logging Out With AspNet.Security.OpenIdConnect.Server (ASP.NET vNext)

I am using Visual Studio 2015 Enterprise and ASP.NET vNext Beta8 to issue and consume JWT tokens as described here.
In our implementation we're storing some client details in Redis at token issuing time and we would like the flush this information when the user logs out.
My question is what is the best practices for logging out with OIDC?
While I could roll my own contoller for this purpose I couldn't help but notice Open ID Connect (OIDC) seems somewhat primed to handle this case. For example OIDC has an OnLogoutEndpoint handler and LogoutEndpointPath settings. But when I call the OIDC logout URI that handler appears to accept any random x-www-form-urlencoded form I throw at it and doesn't in any particular way seem to be demanding the presence of a token.
Any advice on proper OIDC logout practices would be very much appreciated.
In AspNet.Security.OpenIdConnect.Server, the logic used for the logout endpoint is left as an exercise.
In this sample, it is implemented using an MVC 6 controller, where you're - of course - free to add custom logic to remove cached details from your Redis server.
[HttpPost("~/connect/logout")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Logout() {
// When invoked, the logout endpoint might receive an unauthenticated request if the server cookie has expired.
// When the client application sends an id_token_hint parameter, the corresponding identity can be retrieved using AuthenticateAsync.
var identity = await HttpContext.Authentication.AuthenticateAsync(OpenIdConnectServerDefaults.AuthenticationScheme);
// Remove the cached details here. If you need to determine
// who's the authenticated user, you can use the identity variable.
// Remove the authentication cookie and return the user to the client application.
return SignOut("ServerCookie", OpenIdConnectServerDefaults.AuthenticationScheme);
}
You can also do something similar directly from the LogoutEndpoint event. Don't forget to call context.HandleResponse() to make sure the request is not intercepted by another middleware.

Resources