I need an example or pointers for using Keycloak.js authentication in an Aurelia.js-based single page web application. In my use case, a user should be able to access my web SPA before login. However, to gain access to additional resources, user will need to log in. No problem with with the backend apps. 'Just need web-client help.
I have basic HTML5 and Angular.js examples. It seems the example provided by bandrzejczak comes the closest.
'Have already searched throughout the web, read the Keycloak, Aurelia, Aurelia-Auth, Aurelia-Authorization docs. I have spent way too much time on this and am hoping someone has already solved this problem. -- Thanks
See Aurelia-Keycloak.
Aurelia-Keycloak
Alpha version. An authentication plugin based on KeyCloak for Aurelia applications.
Get Started
Install Aurelia-Keycloak:
jspm install aurelia-keycloak
Add keycloak configuration and initialization settings:
Follow Keycloak directions for creating a keycloak.json configuration file. Put this file in the same directory as your application's index.html file. Refer to the keycloak javascript adapter documentation for its initialization options and API.
Add plugin to your app's main.js. This example assumes your keycloak.json is in your root directory. This code will immediately cause the login screen to appear.
.plugin('aurelia-keycloak', {initOptions:{ onLoad: 'login-required' }})
To defer login, use the following:
.plugin('aurelia-keycloak')
Then, construct a login button within your code to call the keycloak login function.
Rather than use a keycloak.json file, you can insert the installation config with the plugin declaration
`.plugin('aurelia-keycloak',{install:{PASTE GENERATED KEYCLOAK.JSON HERE}},initOptions:{ onLoad: 'login-required' }}
See the GITHUB for details.
Related
I am building my first ever Chrome browser extension and I am struggling to find the right solution for handling authentication. There is a requirement that the extension stay logged in as long as possible, to reduce the need for the user to log in often. This means we would need to use Refresh Tokens. I would very much like to handle all authentication on the background script but this is no longer persistent in MV3 nor does it have access to the DOM.
This being the case, I see these options:
use Auth0 React SDK on the content scripts - this means all my authentication logic will run in a somewhat less secure environment but the token will be handled by the library and I will be able to access it in all my content and popup scripts (if I need persistence across page refreshes, I would still need to use localStorage, I believe). But this means that the background script will not have access to the token and it will need one of the other scripts to retrieve it and send it through a message
implement the Authorization Code Flow with PKCE following the steps in this tutorial on the background script - this will mean that all my auth logic is running in a more secure environment but I don't have a way of storing the token, other than using chrome.storage. It's also a bit tricky to silently retrieve the token (or check if user is still logged in) from the background script (it can be done using an injected iframe and the web_message response type or with chrome.identitybut there are still issues with the redirect_uri which needs to be listed in the Allowed Origin config of the Auth0 app - so you can only easily do this on the pages of the extension).
I know that the recommended solution for an SPA is using the SDK but I would like to know if this is also the right solution for a browser extension. Based on this article on Token Storage, localStorage is dangerous especially due to third-party scripts. Seeing that the MV3 manifest has now removed the ability to execute remote code, is localStorage an acceptable way to store tokens?
I have implemented both options using the docs provided but I am unsure as to what is the best solution, given the changes introduced by MV3.
Thank you
I am trying to build an action messaging extension with a task module implementation which uses a URL attribute to load the page. Attached is the screenshot of the task module code which was generated by Yeoman Teams generator.
The popup comes up blank. So it means it's not loading the HTML file path, but if I open Chrome and try to load the URL, it works fine.
Also instead of using URL if I use an adaptive card it works fine. Only the URL part doesn't load on the popup. Attached is another screenshot of the popup inside teams:
What could be wrong with the code?
The other answer is correct in that your url needs to be reflected 100% correctly in your manifest. However, there are a few things that you need to be clear on:
It's not per se the address of the BOT that's important, but rather the address of the web page itself that needs to be listed in your safe domains list in your manifest. In your case, they're hosted in the same endpoint, but they might not be in your final solution, depending on how you end up hosting this.
While you're developing locally, rather use App Studio. That way, you don't need to fiddle with the zip file every time - you can just change it in App Studio and immediately redeploy with the updated URL
Every time when you compile and run the project, a new hostname is generated since ngrok free license is used in the yo teams scaffolding, which makes the app to reference to the old URL.
You need to uninstall the app from the Teams app store under your organization and upload the new app from the package folder .zip (Only after gulp ngrok-serve)
If it still does not work, check the below
Unzip the package file and verify the manifest whether it's pointing to the right hostname of the action html page
Go to http://localhost:4040 to inspect the ngrok tunnel traffic that should give more info on the routed requests.
What's the best practices to hide or prevent the user see the credentials (implemented in WebService calls). The development is ReactJS and use Heroku to deploy the WebApp.
I have this code:
I want to prevent the user can see the credentials and some security details.
I started using the node module dotenv recently and really like how easy it is to use. All you need to do is install it and create a .env file with your environment variables like this:
.env
SECRET_KEY=123456
ANOTHER_KEY=78901
Then, require it as early as possible in your application:
require('dotenv').config().
I do this inside my server.js file (or whatever you name it).
That's it! Anything stored in the file can now be accessed by doing process.env.{name}
For example:
let secret = process.env.SECRET_KEY;
console.log(secret); // 123456
This is not really possible to do in a client side because all the HTTP calls can be easily visible in Network tab in Chrome Inspect Elements(or any web browser).
I would suggest you work on the security so you don't care if a user will see your HTTP endpoints or not.
You can also consider making your HTTP request on a server which will act as a bridge between your client and an API.
I have ASP.NET Core application with IdentityServer4 using ASP.NET Core Identity (based on excellent quickstart).
http://docs.identityserver.io/en/release/quickstarts/6_aspnet_identity.html
In the walkthrough blog they talk about navigating to localhost:5000/Account/Register to create a new user in the Identity db.
When i navigate to that url i get a white page. Furthermore I don't have a Register.cshmtl page or a Register route or anything with the term Register in it.
Did i get the wrong branch? because i am on the release and using core 2.0
I'm new at this and apologize if i'm missing something obvious.
I have run the dotnet ef command but can't see a db anywhere I look - like in sql express or LocalDb.
I am running the Identity server project out of vs17 on port 5000
If i run the MvcClient project I see the home page with the Secure link. If i click that i am directed to the IS4 instance but alice nor bob login will work. (invalid us/pw).
And i can see in the logs that alice and bob users are not being created in-memory
You probably got this by now, but it might interest someone else.
The Quickstart UI repository is not a direct implementation of the tutorials in the IdentityServer4 docs. If you follow the docs, you will first create a new ASP.NET Core MVC application with Individual User Accounts authentication, and that template will create the registration page.
I think your problem is about routing. With scaffolding Identity and specifying routing Your problem will be resolved.
To maintain full control of the Identity UI, run the Identity
scaffolder and select Override all files.
replace
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
with
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
.AddRazorPagesOptions(options =>
{
options.AllowAreas = true;
options.Conventions.AuthorizeAreaFolder("Identity", "/Account/Manage");
options.Conventions.AuthorizeAreaPage("Identity", "/Account/Logout");
});
services.ConfigureApplicationCookie(options =>
{
options.LoginPath = $"/Identity/Account/Login";
options.LogoutPath = $"/Identity/Account/Logout";
options.AccessDeniedPath = $"/Identity/Account/AccessDenied";
});
// using Microsoft.AspNetCore.Identity.UI.Services;
services.AddSingleton<IEmailSender, EmailSender>();
Now you can access to Register account page:
http://localhost:5000/Identity/Account/Register
You also can also change default route like what you want (localhost:5000/Account/Register) for this purpose check this post
I'm developing an Asp.net MVC + Web API + AngularJS SPA. I would like to have several types of registration/authentication:
own profile provider
external providers ie Google, FB etc.
Possible scenarios
As I'm having an SPA it would be best if I could keep my user on my page while external (or internal for that matter) would be taking place. I'd display a modal layer with particular content loaded (maybe even inside an iframe). Can this be done? Online examples?
Have login/registration capability implemented as usual Asp.net MVC full page reload controller/views and then redirect back to my SPA when that is successful. Also redirect to external provider if users wanted to authenticate/register using external provider.
Any other possibility?
Questions
How did you do this similar scenario in your SPA or how would you recommend to do it?
Should I be using particular authentication patterns regarding this - for instance provide my internal authentication/registration similar to external one so SAP would always behave in the same way
I will also have to authenticate my Web API calls subsequently after user athenticated themselves in the SPA. Any guidance on that?
I can only comment on my own experience, maybe it is helpful. We use the same stack as you, Asp.net MVC + Web API + AngularJS. We use server-side MVC for authentication (Microsoft.AspNet.Identity), since we are not exposing a public API at this stage and the only consumer of the API will be our SPA this works perfectly with the least amount of effort.
This also enables us to set a UserContext Angular service on the server once logged in that can be shared through your entire Angular app, the Google Doubleclick Manager guys goes into some of the benefits of this approach during there ng-conf presentation. Since Web Api supports Asp.Net Identity, authentication and authorization works seamlessly between MVC and Web Api.
To sum up the major pros and cons:
Pros:
Very easy and quick to implement.
Works across MVC and Web Api.
Clientside code does not need to be concerned with authentication code.
Set UserContext Angular service on server side once during login, easily shared throughout SPA using Angular DI. See presentation as mentioned above.
Integrates with external providers as easily as you would with any normal MVC app.
Cons:
Since the browser does not send the hash # part of the URL to the server, return URL on login will always be the root of your SPA. E.g. suppose your SPA root is /app, and you try to access /app#/client when you aren't authenticated, you will be redirected to the login page, but the return URL will be /app and not /app#/client as the server has no way to know the hash part of the URL as the browser never sends this.
Not really supported design if you plan to make your your Web Api available outside your SPA. Imagine a console app trying to connect to your API?
So in short, the MVC view that we use to bootstrap our SPA is protected with [Authorize] as well as our Web Api methods. Inside the MVC view we also initialize our UserContext Angular service using Razor to inject whatever user properties we want to expose. Once the SPA is loaded via the single Razor view, everything else is handled via Angular.
We have used what Beyers described before and it works well for most apps, and I use it frequently.
In our current application we are working on the premise that separation of concern should apply to route management.
Normal lifecycle:
User goes to www.server.com
Server sends down index.html
Client makes request for minified assets (.js, .css., etc.)
Angular loads -- a directive removes the loading class from the body (revealing the login section)
The Angular LoginCtrl makes an autologin attempt. (Login and Autologin in an Angular service).
The server returns a HTTP 401
The login screen remains visible.
User successfully logs in ( server gives the browser a authToken cookie; angular does not know or care)
Angular sets some isAuthenticated variables in the BodyCtrl and LoginCtrl
The login section receives a class of .hidden and the content recieves a class of .visible (insert ng-hide/show animations for fun)
User starts filling out a form, but takes an obligitory, 30 minute phone call from relative.
Server has expired his session 10 minutes ago
User finishes and submits form but the server return unauthorized (401)
http-auth-interceptor intercepts the 401 from the server, caches the submit call and publishes a "login-required' event.
The BodyCtrl listens and sets isAuthenticated = false and then the ng-class and ng-show/hide do there work on the login and content sections.
User re-signs in and 'login-confirmed' event is published
http-auth-interceptor posts cached call.
User is happy
(the content section can also display some public views as our rest api has some routes that are made public -- displaying the public views is handled by a simple function similar to isAuthenticated)
Angular Ctrl structure:
index.html
<body>
<!-- I am a fullscreen login element, z-index=2000-->
<div data-ng-controller="LoginCtrl" data-ng-hide="isAuthenticated()"</div>
<div data-ng-controller="ContentCtrl">
<!-- fullscreen class has a z-index=2001 -->
<section data-ng-view data-ng-class="{fullscreen: isViewPublic()}"></section>
<!-- header and nav go here -->
</div>
</body>
We could get a little more creative on how display the public views/routes but you get the idea. We only have a few public routes and they are mainly for registration, password resets, etc.
Disclaimer: I have yet to integrate with and oauth/external authentication services. Hopefully this setup will still hold water.
Any critique of this process is welcome.
By no means am I familiar with Microsoft backends, but still I'll give it a try ;-) :
Good resources on how the authentication/authorisation should be done in Angular-based SPA:
https://github.com/fnakstad/angular-client-side-auth
live demo: http://angular-client-side-auth.herokuapp.com/login
As you requested there are 2 methods of authenticating:
own profile
external providers.
It redirects to the provider website though :-/
NodeJS on the backend
Good ng-conf talk on how authorisation is done in Google Doubleclick Manager application: http://www.youtube.com/watch?v=62RvRQuMVyg&t=2m29s
It's not quite what you want (authentication), but the solution begins to kick in on the authentication phase. Furthermore it may be useful later and the approach Ido is presenting seems really sound.
Slides: https://docs.google.com/file/d/0B4F6Csor-S1cNThqekp4NUZCSmc/edit
Last but not least: Mastering Web Application Development with AngularJS.
A brilliant Angular book by Paweł Kozłowski and Pete Bacon Darwin.
It has a whole chapter or two dedicated to auth- stuff. It shows some complex solutions, such as retrial and session-expired interceptors. But even if you will not use approaches from the book directly, those chapters are still a must-reads since they may give you an inspiration for devising your own auth- solutions.
Remark - http-auth-interceptor: As it is mentioned in the book, the securityInterceptor solution was originally invented by Witold Szczerba. See the blog post.
http-auth-interceptor code, mentioned by #CorySilva, is actually sample code to concepts explained in the post.
btw: Those 2 chapters are great, but I hope that the Community comes up with some easier solutions in the future. Every time I read this interceptor promise api-based code I get a severe headache :)
btw2: If somebody doesn't consider oneself an Angular expert, the entire book is definetly a must-read and great complement after reading the Guide
As for building the login page with ASP - I suggest using ASP only as a backend and middleware and drawing whole the app with Angular.
You can start with your approach and switch to the pure-Angular SPA if it will begin to require more and more crazy hacks to make technologies play together nicely.
But I might be wrong and this particular case won't require applying any hacks.