| <!DOCTYPE html> |
| <html> |
| <head> |
| <meta charset="utf-8"> |
| <meta http-equiv="X-UA-Compatible" content="IE=edge"> |
| <meta name="viewport" content="width=device-width, initial-scale=1"> |
| <meta name="description" content=""> |
| <meta name="keywords" content="keycloak, user management, permissions, authentication"> |
| <title>Che Authentication | Eclipse Che Documentation</title> |
| <link rel="stylesheet" href="css/syntax.css"> |
| |
| <link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" crossorigin="anonymous"> |
| <!--<link rel="stylesheet" type="text/css" href="css/bootstrap.min.css">--> |
| <link rel="stylesheet" href="css/modern-business.css"> |
| <!-- Latest compiled and minified CSS --> |
| <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> |
| <link rel="stylesheet" href="css/customstyles.css"> |
| <link rel="stylesheet" href="css/boxshadowproperties.css"> |
| <!-- most color styles are extracted out to here --> |
| <link rel="stylesheet" href="css/theme-che.css"> |
| |
| |
| <link rel="stylesheet" href="/css/coderay.css" media="screen" type="text/css"> |
| |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js" crossorigin="anonymous"></script> |
| |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.min.js" crossorigin="anonymous"></script> |
| <script src="js/jquery.navgoco.min.js"></script> |
| |
| |
| <!-- Latest compiled and minified JavaScript --> |
| <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script> |
| <!-- Anchor.js --> |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/anchor-js/2.0.0/anchor.min.js" crossorigin="anonymous"></script> |
| <script src="js/toc.js"></script> |
| <script src="js/customscripts.js"></script> |
| |
| <link rel="shortcut icon" href="che/docs/images/favicon.ico"> |
| |
| <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries --> |
| <!-- WARNING: Respond.js doesn't work if you view the page via file:// --> |
| <!--[if lt IE 9]> |
| <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script> |
| <script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script> |
| <![endif]--> |
| |
| <link rel="alternate" type="application/rss+xml" title="che" href="http://0.0.0.0:4000/feed.xml"> |
| |
| <script> |
| $(document).ready(function() { |
| // Initialize navgoco with default options |
| $("#mysidebar").navgoco({ |
| caretHtml: '', |
| accordion: true, |
| openClass: 'active', // open |
| save: false, // leave false or nav highlighting doesn't work right |
| cookie: { |
| name: 'navgoco', |
| expires: false, |
| path: '/' |
| }, |
| slide: { |
| duration: 400, |
| easing: 'swing' |
| } |
| }); |
| |
| $("#collapseAll").click(function(e) { |
| e.preventDefault(); |
| $("#mysidebar").navgoco('toggle', false); |
| }); |
| |
| $("#expandAll").click(function(e) { |
| e.preventDefault(); |
| $("#mysidebar").navgoco('toggle', true); |
| }); |
| |
| }); |
| |
| </script> |
| <script> |
| $(function () { |
| $('[data-toggle="tooltip"]').tooltip() |
| }) |
| </script> |
| <script> |
| $(document).ready(function() { |
| $("#tg-sb-link").click(function() { |
| $("#tg-sb-sidebar").toggle(); |
| $("#tg-sb-content").toggleClass('col-md-9'); |
| $("#tg-sb-content").toggleClass('col-md-12'); |
| $("#tg-sb-icon").toggleClass('fa-toggle-on'); |
| $("#tg-sb-icon").toggleClass('fa-toggle-off'); |
| }); |
| }); |
| </script> |
| |
| |
| </head> |
| <body> |
| <!-- Navigation --> |
| <nav class="navbar navbar-inverse navbar-static-top"> |
| <div class="container topnavlinks"> |
| <div class="navbar-header"> |
| <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1"> |
| <span class="sr-only">Toggle navigation</span> |
| <span class="icon-bar"></span> |
| <span class="icon-bar"></span> |
| <span class="icon-bar"></span> |
| </button> |
| <a class="fa fa-home fa-lg navbar-brand" href="index.html"> <span class="projectTitle"> Eclipse Che Documentation</span></a> |
| </div> |
| <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> |
| <ul class="nav navbar-nav navbar-right"> |
| <!-- toggle sidebar button --> |
| <li><a id="tg-sb-link" href="#"><i id="tg-sb-icon" class="fa fa-toggle-on"></i> Nav</a></li> |
| <!-- entries without drop-downs appear here --> |
| |
| |
| |
| |
| |
| |
| |
| <li><a href="https://medium.com/eclipse-che-blog/" target="_blank">Blog</a></li> |
| |
| |
| |
| <li><a href="https://github.com/eclipse/che" target="_blank">Source Code</a></li> |
| |
| |
| |
| <!-- entries with drop-downs appear here --> |
| <!-- conditional logic to control which topnav appears for the audience defined in the configuration file.--> |
| |
| |
| <li class="dropdown"> |
| <a href="#" class="dropdown-toggle" data-toggle="dropdown">Get Support<b class="caret"></b></a> |
| <ul class="dropdown-menu"> |
| |
| |
| <li><a href="https://github.com/eclipse/che/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3Akind%2Fbug" target="_blank">Known Bugs</a></li> |
| |
| |
| |
| <li><a href="https://github.com/eclipse/che/issues/new" target="_blank">File an Issue</a></li> |
| |
| |
| |
| <li><a href="https://stackoverflow.com/questions/tagged/eclipse-che" target="_blank">Che on StackOverflow</a></li> |
| |
| |
| </ul> |
| </li> |
| |
| |
| <!-- |
| <li> |
| |
| |
| |
| <a class="email" title="Submit feedback" href="#" onclick="javascript:window.location='mailto:?subject= feedback&body=I have some feedback about the Che Authentication page: ' + window.location.href;"><i class="fa fa-envelope-o"></i> Feedback</a> |
| |
| </li> |
| --> |
| |
| <!--comment out this block if you want to hide search--> |
| <li> |
| <!--start search--> |
| <div id="search-demo-container"> |
| <input type="text" id="search-input" placeholder="search..."> |
| <ul id="results-container"></ul> |
| </div> |
| <script src="js/jekyll-search.js" type="text/javascript"></script> |
| <script type="text/javascript"> |
| SimpleJekyllSearch.init({ |
| searchInput: document.getElementById('search-input'), |
| resultsContainer: document.getElementById('results-container'), |
| dataSource: 'search.json', |
| searchResultTemplate: '<li><a href="{url}" title="Che Authentication">{title}</a></li>', |
| noResultsText: 'No results found.', |
| limit: 10, |
| fuzzy: true, |
| }) |
| </script> |
| <!--end search--> |
| </li> |
| </ul> |
| </div> |
| </div> |
| <!-- /.container --> |
| </nav> |
| |
| <!-- Page Content --> |
| <div class="container"> |
| <div id="main"> |
| <!-- Content Row --> |
| <div class="row"> |
| |
| |
| <!-- Sidebar Column --> |
| <div class="col-md-3" id="tg-sb-sidebar"> |
| |
| |
| <ul id="mysidebar" class="nav"> |
| <li class="sidebarTitle"> </li> |
| |
| |
| |
| |
| |
| <li> |
| <a href="#">Overview</a> |
| <ul> |
| |
| |
| |
| <li><a href="index.html">Introduction</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="quick-start.html">Getting Started</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="single-multi-user.html">Single and Multi-User Flavors</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="infra-support.html">Supported Infrastructures</a></li> |
| |
| |
| |
| |
| </ul> |
| </li> |
| |
| |
| |
| <li> |
| <a href="#">Che on Docker</a> |
| <ul> |
| |
| |
| |
| <li><a href="docker-single-user.html">Docker - Single User</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="docker-multi-user.html">Docker - Multi User</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="docker-config.html">Docker - Configuration</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="docker-cli.html">Docker - CLI Reference</a></li> |
| |
| |
| |
| |
| </ul> |
| </li> |
| |
| |
| |
| <li> |
| <a href="#">Che on Kubernetes</a> |
| <ul> |
| |
| |
| |
| <li><a href="kubernetes-single-user.html">Kubernetes - Single User</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="kubernetes-multi-user.html">Kubernetes - Multi User</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="kubernetes-config.html">Kubernetes - Configuration</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="kubernetes-admin-guide.html">Kubernetes - Admin Guide</a></li> |
| |
| |
| |
| |
| </ul> |
| </li> |
| |
| |
| |
| <li> |
| <a href="#">Che on OpenShift</a> |
| <ul> |
| |
| |
| |
| <li><a href="openshift-single-user.html">OpenShift - Single User</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="openshift-multi-user.html">OpenShift - Multi User</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="openshift-config.html">OpenShift - Configuration</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="openshift-admin-guide.html">OpenShift - Admin Guide</a></li> |
| |
| |
| |
| |
| </ul> |
| </li> |
| |
| |
| |
| <li> |
| <a href="#">User Management</a> |
| <ul> |
| |
| |
| |
| <li><a href="user-management.html">Authentication and Authorization</a></li> |
| |
| |
| |
| |
| |
| |
| <li class="active"><a href="authentication.html">Security Model</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="permissions.html">Permissions</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="organizations.html">Organizations in UD</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="resource-management.html">Resource Management</a></li> |
| |
| |
| |
| |
| </ul> |
| </li> |
| |
| |
| |
| <li> |
| <a href="#">User Guides</a> |
| <ul> |
| |
| |
| |
| <li><a href="creating-starting-workspaces.html">Creating and starting Workspaces</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="ide-projects.html">Projects</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="editor-code-assistance.html">Editor and Code-Assistance</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="dependency-management.html">Dependency Management</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="commands-ide-macro.html">Commands and IDE Macros</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="version-control.html">Version Control</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="debug.html">Debug</a></li> |
| |
| |
| |
| |
| </ul> |
| </li> |
| |
| |
| |
| <li> |
| <a href="#">Workspace Administration</a> |
| <ul> |
| |
| |
| |
| <li><a href="what-are-workspaces.html">Workspace Overview</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="stacks.html">Workspace - Stacks</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="recipes.html">Workspace - Recipes</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="servers.html">Workspace - Servers</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="installers.html">Workspace - Installers</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="volumes.html">Workspace - Volumes Mount</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="env-variables.html">Workspace - Environment Variables</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="projects.html">Workspace - Projects</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="workspaces-troubleshooting.html">Workspace - Troubleshooting</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="workspace-data-model.html">Workspace Data Model</a></li> |
| |
| |
| |
| |
| </ul> |
| </li> |
| |
| |
| |
| <li> |
| <a href="#">Portable Workspaces</a> |
| <ul> |
| |
| |
| |
| <li><a href="chedir-getting-started.html">Chedir - Getting Started</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="why-chedir.html">Chedir - Why Chedir?</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="chedir-installation.html">Chedir - Installation</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="chedir-project-setup.html">Chedir - Project Setup</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="chedir-up-and-down.html">Chedir - Up and Down</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="chefile.html">Chedir - Chefile</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="chedir-ssh.html">Chedir - SSH</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="factories-getting-started.html">Factory - Getting Started</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="creating-factories.html">Factory - Creating</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="factories_json_reference.html">Factory - JSON Reference</a></li> |
| |
| |
| |
| |
| </ul> |
| </li> |
| |
| |
| |
| <li> |
| <a href="#">Developer Guides</a> |
| <ul> |
| |
| |
| |
| <li><a href="framework-overview.html">Overview</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="rest-api.html">SDK - REST API</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="che-in-che-quickstart.html">SDK - Your First Plugin</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="build-reqs.html">SDK - Building Che</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="assemblies.html">SDK - Assemblies</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="logging.html">SDK - Logging</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="ide-extensions-gwt.html">SDK - GWT IDE Extensions</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="server-side-extensions.html">SDK - Server Side Extensions</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="custom-installers.html">SDK - Installers</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="project-types.html">SDK - Project Types</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="language-servers.html">SDK - Language Support</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="parts.html">IDE UI: Parts</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="actions.html">IDE UI: Actions</a></li> |
| |
| |
| |
| |
| </ul> |
| </li> |
| |
| |
| |
| <li> |
| <a href="#">Dev Essentials</a> |
| <ul> |
| |
| |
| |
| <li><a href="guice.html">Dependency Injection</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="dto.html">Transport: DTO</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="json-rpc.html">Communication: JSON-RPC</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="handling-projects-in-plugins.html">Handling Projects in Plugins</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="dao.html">Persistence, DAO</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="properties.html">Properties</a></li> |
| |
| |
| |
| |
| </ul> |
| </li> |
| |
| |
| |
| <li> |
| <a href="#">Infrastructure and SPI</a> |
| <ul> |
| |
| |
| |
| <li><a href="spi_overview.html">Overview</a></li> |
| |
| |
| |
| |
| |
| |
| <li><a href="spi-implementation.html">Implementation Notes</a></li> |
| |
| |
| |
| |
| </ul> |
| </li> |
| |
| |
| |
| <!-- if you aren't using the accordion, uncomment this block: |
| <p class="external"> |
| <a href="#" id="collapseAll">Collapse All</a> | <a href="#" id="expandAll">Expand All</a> |
| </p> |
| --> |
| </ul> |
| |
| <!-- this highlights the active parent class in the navgoco sidebar. this is critical so that the parent expands when you're viewing a page. This must appear below the sidebar code above. Otherwise, if placed inside customscripts.js, the script runs before the sidebar code runs and the class never gets inserted.--> |
| <script>$("li.active").parents('li').toggleClass("active");</script> |
| |
| </div> |
| |
| |
| |
| |
| <!-- Content Column --> |
| <div class="col-md-9" id="tg-sb-content"> |
| <div class="post-header"> |
| <h1 class="post-title-main">Che Authentication</h1> |
| </div> |
| |
| |
| |
| <div class="post-content"> |
| |
| |
| |
| |
| |
| <!-- this handles the automatic toc. use ## for subheads to auto-generate the on-page minitoc. if you use html tags, you must supply an ID for the heading element in order for it to appear in the minitoc. --> |
| <script> |
| $( document ).ready(function() { |
| // Handler for .ready() called. |
| $('#toc').toc({ minimumHeaders: 0, listType: 'ul', showSpeed: 0, headers: 'h2' }); |
| /* this offset helps account for the space taken up by the floating toolbar. */ |
| $('#toc').on('click', 'a', function() { |
| var target = $(this.getAttribute('href')) |
| , scroll_target = target.offset().top |
| $(window).scrollTop(scroll_target - 10); |
| return false |
| }) |
| |
| }); |
| </script> |
| |
| <div id="toc"></div> |
| |
| |
| |
| |
| <!-- |
| |
| |
| --> |
| |
| <div class="sect1"> |
| <h2 id="authentication-on-che-master">Authentication on Che Master</h2> |
| <div class="sectionbody"> |
| <div class="sect2"> |
| <h3 id="openid">OpenId</h3> |
| <div class="paragraph"> |
| <p>OpenId authentication on Che master, implies presence of an external OpenId provider and has 2 main steps:</p> |
| </div> |
| <div class="olist arabic"> |
| <ol class="arabic"> |
| <li> |
| <p>Authenticate the user through the JWT token he brought or redirect him to login;</p> |
| <div class="paragraph"> |
| <p>(Authentication tokens should be send in a <code>Authorization</code> header. Also, in limited cases when it’s not possible to use <code>Authorization</code> header, token can be send in <code>token</code> query parameter. An example of such exceptional case can be: OAuth authentification initialization, IDE shows javadoc in iframe where authentication must be initialized.)</p> |
| </div> |
| </li> |
| <li> |
| <p>Compose internal "subject" object which represents the current user inside of the Che master code.</p> |
| </li> |
| </ol> |
| </div> |
| <div class="paragraph"> |
| <p>At the time of writing the only supported/tested OpenId provider is Keycloak, so all examples/links will refer to this implementation.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The flow starts from the settings service where clients can find all the necessary URLs and properties of the OpenId provider such as <code>jwks.endpoint</code>, <code>token.endpoint</code>, <code>logout.endpoint</code>, <code>realm.name</code>, <code>client_id</code> etc returned. in JSON format.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Service class is <strong>org.eclipse.che.multiuser.keycloak.server.KeycloakSettings</strong>, and it is bound only in multi-user version of Che, so by its presence it is possible to detect if authentication enabled in current deployment or not.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Example output:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="json">{ |
| <span class="key"><span class="delimiter">"</span><span class="content">che.keycloak.token.endpoint</span><span class="delimiter">"</span></span>: <span class="string"><span class="delimiter">"</span><span class="content">http://172.19.20.9:5050/auth/realms/che/protocol/openid-connect/token</span><span class="delimiter">"</span></span>, |
| <span class="key"><span class="delimiter">"</span><span class="content">che.keycloak.profile.endpoint</span><span class="delimiter">"</span></span>: <span class="string"><span class="delimiter">"</span><span class="content">http://172.19.20.9:5050/auth/realms/che/account</span><span class="delimiter">"</span></span>, |
| <span class="key"><span class="delimiter">"</span><span class="content">che.keycloak.client_id</span><span class="delimiter">"</span></span>: <span class="string"><span class="delimiter">"</span><span class="content">che-public</span><span class="delimiter">"</span></span>, |
| <span class="key"><span class="delimiter">"</span><span class="content">che.keycloak.auth_server_url</span><span class="delimiter">"</span></span>: <span class="string"><span class="delimiter">"</span><span class="content">http://172.19.20.9:5050/auth</span><span class="delimiter">"</span></span>, |
| <span class="key"><span class="delimiter">"</span><span class="content">che.keycloak.password.endpoint</span><span class="delimiter">"</span></span>: <span class="string"><span class="delimiter">"</span><span class="content">http://172.19.20.9:5050/auth/realms/che/account/password</span><span class="delimiter">"</span></span>, |
| <span class="key"><span class="delimiter">"</span><span class="content">che.keycloak.logout.endpoint</span><span class="delimiter">"</span></span>: <span class="string"><span class="delimiter">"</span><span class="content">http://172.19.20.9:5050/auth/realms/che/protocol/openid-connect/logout</span><span class="delimiter">"</span></span>, |
| <span class="key"><span class="delimiter">"</span><span class="content">che.keycloak.realm</span><span class="delimiter">"</span></span>: <span class="string"><span class="delimiter">"</span><span class="content">che</span><span class="delimiter">"</span></span> |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Also, this service allows to download JS client library to interact with provider. Service URL is <code><che.host>:<che.port>/api/keycloak/settings</code> for retrieving settings JSON and <code><che.host>:<che.port>/api/keycloak/OIDCKeycloak.js</code> for JS adapter library.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Next step is redirection of user to the appropriate provider’s login page with all the necessary params like client_id, return redirection path etc. This can be basically done with any client library (JS or Java etc).</p> |
| </div> |
| <div class="paragraph"> |
| <p>After user logged in on provider’s side and client side code obtained and passed the JWT token, validation of it and creation of subject begins.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Verification of tokens signature occurs in the two main filters chain:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><strong>org.eclipse.che.multiuser.keycloak.server.KeycloakAuthenticationFilter</strong> class. Token is extracted from <code>Authorization</code> header or <code>token</code> query param and tried to being parsed using public key retrieved from provider. In case of expired/invalid/malformed token, 403 error is sent to user. As noted above, usage of query parameter should be minimised as much as possible, since support of it may be limited/dropped at some point.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>If validation was successful, token is passed to the</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><strong>org.eclipse.che.multiuser.keycloak.server.KeycloakEnvironmentInitalizationFilter</strong> filter in the parsed form. This filter simply extracts data from JWT token claims, creates user in the local DB if it is not yet present, and constructs subject object and sets it into per-request <code>EnvironmentContext</code> object which is statically accessible everywhere.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>If the request was made using machine token only (e.g. from ws agent) then it is only one auth filter in the chain:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><strong>org.eclipse.che.multiuser.machine.authentication.server.MachineLoginFilter</strong> - finds userId given token belongs to, than retrieves user instance and sets principal to the session.</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Master-to-master requests are performed using <strong>org.eclipse.che.multiuser.keycloak.server.KeycloakHttpJsonRequestFactory</strong> which signs every request with the current subject token obtained from EnvironmentContext.</p> |
| </div> |
| <div class="sect3"> |
| <h4 id="user-profile">User Profile</h4> |
| <div class="paragraph"> |
| <p>Since keycloak may store user specific information (first/last name, phone number, job title etc), there is special implementation of the ProfileDao which can provide this data to consumers inside Che. Implementation is read-only, so no create/update operations are possible. Class is <strong>org.eclipse.che.multiuser.keycloak.server.dao.KeycloakProfileDao</strong>.</p> |
| </div> |
| </div> |
| <div class="sect3"> |
| <h4 id="obtaining-token-from-keycloak">Obtaining Token From Keycloak</h4> |
| <div class="paragraph"> |
| <p>For the clients which cannot run JS or other type clients (like CLI or selenium tests), auth token may be requested directly from Keycloak. The simplest way to obtain Keycloak auth token, is to perform request to the token endpoint with username and password credentials. This request can be schematically described as following cURL request:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre>curl |
| --data "grant_type=password&client_id=<client_name>&username=<username>&password=<password>" |
| http://<keyckloak_host>:5050/auth/realms/<realm_name>/protocol/openid-connect/token</pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Since the two main Che clients (IDE and Dashboard) utilizes native Keycloak js library, they’re using a customized Keycloak login page and somewhat more complicated authentication mechanism using <code>grant_type=authorization_code</code>. It’s a two step authentication: first step is login and obtaining authorization code, and second step is obtaining token using this code.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Example of correct token response:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="json">{ |
| <span class="key"><span class="delimiter">"</span><span class="content">access_token</span><span class="delimiter">"</span></span>:<span class="string"><span class="delimiter">"</span><span class="content">eyJhb...<rest of JWT token here></span><span class="delimiter">"</span></span>, |
| <span class="key"><span class="delimiter">"</span><span class="content">expires_in</span><span class="delimiter">"</span></span>:<span class="integer">300</span>, |
| <span class="key"><span class="delimiter">"</span><span class="content">refresh_expires_in</span><span class="delimiter">"</span></span>:<span class="integer">1800</span>, |
| <span class="key"><span class="delimiter">"</span><span class="content">refresh_token</span><span class="delimiter">"</span></span>:<span class="string"><span class="delimiter">"</span><span class="content">Nj0C...<rest of refresh token here></span><span class="delimiter">"</span></span>, |
| <span class="key"><span class="delimiter">"</span><span class="content">token_type</span><span class="delimiter">"</span></span>:<span class="string"><span class="delimiter">"</span><span class="content">bearer</span><span class="delimiter">"</span></span>, |
| <span class="key"><span class="delimiter">"</span><span class="content">not-before-policy</span><span class="delimiter">"</span></span>:<span class="integer">0</span>, |
| <span class="key"><span class="delimiter">"</span><span class="content">session_state</span><span class="delimiter">"</span></span>:<span class="string"><span class="delimiter">"</span><span class="content">14de1b98-8065-43e1-9536-43e7472250c9</span><span class="delimiter">"</span></span> |
| }</code></pre> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="other-authentication-implementations">Other authentication implementations</h3> |
| <div class="paragraph"> |
| <p>If you want to adapt authentication implementation other than Keycloak, the following steps must be done:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>Write own or refactor existing info service which will provide list of configured provider endpoints to the clients;</p> |
| </li> |
| <li> |
| <p>Write single or chain of filters to validate tokens, create user in Che DB and compose the Subject object;</p> |
| </li> |
| <li> |
| <p>If the new auth provider supports OpenId protocol, OIDC JS client available at settings endpoint can be used as well since it is maximally decoupled of specific implementations.</p> |
| </li> |
| <li> |
| <p>If the selected provider stores some additional data about user (first/last name, job title etc), it is a good idea to write an provider-specific ProfileDao implementation which will provide such kind of information.</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="oauth">OAuth</h3> |
| <div class="paragraph"> |
| <p>OAuth authentication part has 2 main flows - internal and external based on Keycloak brokering mechanism. So, there are 2 main OAuth API implementations - <strong>org.eclipse.che.security.oauth.EmbeddedOAuthAPI</strong> and <strong>org.eclipse.che.multiuser.keycloak.server.oauth2.DelegatedOAuthAPI</strong>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>They can be switched using <code>che.oauth.service_mode=<embedded|delegated></code> configuration property.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Also, there is support of OAuth1 protocol can be found at <strong>org.eclipse.che.security.oauth1</strong> package.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The main REST endpoint in tha OAuth API is <strong>org.eclipse.che.security.oauth.OAuthAuthenticationService</strong>, which contains <code>authenticate</code> method to start OAuth authentication flow, <code>callback</code> method to process callbacks from provider, <code>token</code> to retrieve current user’s oauth token, etc.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Those methods refer to the currently activated embedded/delegated OAuthAPI which is doing all the undercover stuff (finds appropriate authenticator, initializes the login process, user forwarding etc).</p> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="authentication-on-che-agents">Authentication on Che Agents</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>Machines may contain services that must be protected with authentication, e.g. agents like workspace agent and terminal. For this purpose, machine authentication mechanism should be used. Machine tokens were introduced to avoid passing the Keycloak tokens to the machine side (which can be potentially insecure). Another reason is that Keycloak tokens may have relatively small lifetime and require periodical renewal/refresh which is hard to manage and keep in sync with same user session tokens on clients etc.</p> |
| </div> |
| <div class="paragraph"> |
| <p>As agents cannot be queried using Keycloak token, there is only Machine Token option. Machine token can be also passed in header or query parameter.</p> |
| </div> |
| <div class="sect2"> |
| <h3 id="machine-jwt-token">Machine JWT Token</h3> |
| <div class="paragraph"> |
| <p>Machine token is <a href="https://jwt.io/">JWT</a> that contains the following information in its claim:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><strong>uid</strong> - id of user who owns this token</p> |
| </li> |
| <li> |
| <p><strong>uname</strong> - name of user who owns this token</p> |
| </li> |
| <li> |
| <p><strong>wsid</strong> - id of a workspace which can be queried with this token</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>Each user is provided with unique personal token for each workspace.</p> |
| </div> |
| <div class="paragraph"> |
| <p>The structure of token and the signature are different to Keycloak and have the following view:</p> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="json"><span class="error">#</span> <span class="error">H</span><span class="error">e</span><span class="error">a</span><span class="error">d</span><span class="error">e</span><span class="error">r</span> |
| { |
| <span class="key"><span class="delimiter">"</span><span class="content">alg</span><span class="delimiter">"</span></span>: <span class="string"><span class="delimiter">"</span><span class="content">RS512</span><span class="delimiter">"</span></span>, |
| <span class="key"><span class="delimiter">"</span><span class="content">kind</span><span class="delimiter">"</span></span>: <span class="string"><span class="delimiter">"</span><span class="content">machine_token</span><span class="delimiter">"</span></span> |
| } |
| <span class="error">#</span> <span class="error">P</span><span class="error">a</span><span class="error">y</span><span class="error">l</span><span class="error">o</span><span class="error">a</span><span class="error">d</span> |
| { |
| <span class="key"><span class="delimiter">"</span><span class="content">wsid</span><span class="delimiter">"</span></span>: <span class="string"><span class="delimiter">"</span><span class="content">workspacekrh99xjenek3h571</span><span class="delimiter">"</span></span>, |
| <span class="key"><span class="delimiter">"</span><span class="content">uid</span><span class="delimiter">"</span></span>: <span class="string"><span class="delimiter">"</span><span class="content">b07e3a58-ed50-4a6e-be17-fcf49ff8b242</span><span class="delimiter">"</span></span>, |
| <span class="key"><span class="delimiter">"</span><span class="content">uname</span><span class="delimiter">"</span></span>: <span class="string"><span class="delimiter">"</span><span class="content">john</span><span class="delimiter">"</span></span>, |
| <span class="key"><span class="delimiter">"</span><span class="content">jti</span><span class="delimiter">"</span></span>: <span class="string"><span class="delimiter">"</span><span class="content">06c73349-2242-45f8-a94c-722e081bb6fd</span><span class="delimiter">"</span></span> |
| } |
| <span class="error">#</span> <span class="error">S</span><span class="error">i</span><span class="error">g</span><span class="error">n</span><span class="error">a</span><span class="error">t</span><span class="error">u</span><span class="error">r</span><span class="error">e</span> |
| { |
| <span class="key"><span class="delimiter">"</span><span class="content">value</span><span class="delimiter">"</span></span>: <span class="string"><span class="delimiter">"</span><span class="content">RSASHA512(base64UrlEncode(header) + . + base64UrlEncode(payload))</span><span class="delimiter">"</span></span> |
| }</code></pre> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>The algorithm that is used for signing machine tokens is <code>SHA-512</code> and it’s not configurable for now. Also, there is no public service that distributes the public part of the key pair with which the token was signed. But in each machine, there must be environment variables that contains key value. So, agents can verify machine JWT token using the following environment variables:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><code>CHE_MACHINE_AUTH_SIGNATURE__ALGORITHM</code> - contains information about the algorithm which the token was signed</p> |
| </li> |
| <li> |
| <p><code>CHE_MACHINE_AUTH_SIGNATURE<em>PUBLIC</em>KEY</code> - contains public key value encoded in Base64</p> |
| </li> |
| </ul> |
| </div> |
| <div class="paragraph"> |
| <p>It’s all that is needed for verifying machine token inside of machine. To make sure that specified token is related to current workspace, it is needed to fetch <code>wsid</code> from JWT token claims and compare it with <code>CHE_WORKSPACE_ID</code> environment variable.</p> |
| </div> |
| <div class="paragraph"> |
| <p>Also, if agents need to query Che Master they can use machine token provided in <code>CHE_MACHINE_TOKEN</code> environment, actually it is token of user who starts a workspace.</p> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="authentication-schema">Authentication schema</h3> |
| <div class="paragraph"> |
| <p>The way how Che master interacts with agents with enabled authentication mechanism is the following:</p> |
| </div> |
| <div class="imageblock"> |
| <div class="content"> |
| <img src="/che/docs/images/diagrams/machine_auth_flow_old.png" alt="machine auth flow old"> |
| </div> |
| </div> |
| <div class="paragraph"> |
| <p>Machine token verification on agents is done by the following components:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p><strong>org.eclipse.che.multiuser.machine.authentication.agent.MachineLoginFilter</strong> - doing basically the same as the appropriate filter on a master, the only thing that is different it’s a way how agent obtains the public signature part. The public key for the signature check is placed in a machine environment, with algorithm description.</p> |
| </li> |
| <li> |
| <p><strong>auth.auth.go</strong> - the entry point for all request that is proceeding on go agents side, the logic of token verification is similar with MachineLoginFilter.</p> |
| </li> |
| </ul> |
| </div> |
| </div> |
| <div class="sect2"> |
| <h3 id="obtaining-machine-token">Obtaining Machine Token</h3> |
| <div class="paragraph"> |
| <p>A machine token is provided for users in runtime object. It can be fetched by using get workspace by key (id or namespace/name) method which path equals to <code>/api/workspace/<workspace_key></code>. The machine token will be placed in <code>runtime.machineToken</code> field.</p> |
| </div> |
| </div> |
| </div> |
| </div> |
| <div class="sect1"> |
| <h2 id="using-swagger-or-rest-clients">Using Swagger or REST Clients</h2> |
| <div class="sectionbody"> |
| <div class="paragraph"> |
| <p>User’s Keycloak token is used to execute queries to secured API on his behalf through REST clients. A valid token must be attached as request header or query parameter - <code>?token=$token</code>. Che Swagger can be accessed from <code><a href="http://che_host:8080/swagger" class="bare">http://che_host:8080/swagger</a></code>. A user must be signed-in through Keycloak so that access token is included in request headers.</p> |
| </div> |
| <div class="paragraph"> |
| <p>By default, swagger loads <code>swagger.json</code> from <a href="che-master.html">Master</a>.</p> |
| </div> |
| <div class="paragraph"> |
| <p>To work with WS Agent, a URL to its <code>swagger.json</code> should be provided. It can be retrieved from <a href="workspace-data-model.html#runtime">Workspace Runtime</a>, by getting URL to <a href="servers">WS Agent server</a> endpoint and adding <code>api/docs/swagger.json</code> to it. Also, to authenticate on WS Agent API, user must include Machine Token, which can be found in Workspace Runtime as well.</p> |
| </div> |
| <div class="paragraph"> |
| <p>To use Swagger for a workspace agent, user must do following steps:</p> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>get workspace object with runtimes fetched (using <code>/api/workspace/<workspace_key></code> service)</p> |
| </li> |
| <li> |
| <p>get WS agent API endpoint URL, and add a path to its <code>swagger.json</code> (e.g. <code><a href="http://<che_host>:<machine_port>/api/docs/swagger.json" class="bare">http://<che_host>:<machine_port>/api/docs/swagger.json</a></code> for Docker or <code><a href="http://<ws-agent-route>/api/docs/swagger.json" class="bare">http://<ws-agent-route>/api/docs/swagger.json</a></code> for OpenShift ). Put it in the upper bar <code>URL</code> field:</p> |
| </li> |
| </ul> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre class="CodeRay highlight"><code data-lang="json"><span class="key"><span class="delimiter">"</span><span class="content">wsagent/http</span><span class="delimiter">"</span></span>: { |
| <span class="key"><span class="delimiter">"</span><span class="content">url</span><span class="delimiter">"</span></span>: <span class="string"><span class="delimiter">"</span><span class="content">http://172.19.20.180:32777/api</span><span class="delimiter">"</span></span>, |
| <span class="key"><span class="delimiter">"</span><span class="content">attributes</span><span class="delimiter">"</span></span>: {}, |
| <span class="key"><span class="delimiter">"</span><span class="content">status</span><span class="delimiter">"</span></span>: <span class="string"><span class="delimiter">"</span><span class="content">RUNNING</span><span class="delimiter">"</span></span> |
| }</code></pre> |
| </div> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>get machine token from <code>runtime.machineToken</code> field, and put it in the upper bar <code>token</code> field</p> |
| </li> |
| </ul> |
| </div> |
| <div class="listingblock"> |
| <div class="content"> |
| <pre>"machineToken": "eyJhbGciOiJSUzUxMiIsImtpbmQiOiJtYWNoaW5lX3Rva2VuIn0.eyJ3c2lkIjoid29ya3NwYWNlMzEiLCJ1aWQiOiJ1c2VyMTMiLCJ1bmFtZSI6InRlc3RVc2VyIiwianRpIjoiOTAwYTUwNWYtYWY4ZS00MWQxLWFhYzktMTFkOGI5OTA5Y2QxIn0.UwU7NDzqnHxTr4vu8UqjZ7-cjIfQBY4gP70Nqxkwfx8EsPfZMpoHGPt8bfqLWVWkpp3OacQVaswAOMOG9Uc9FtLnQWnup_6vvyMo6gchZ1lTZFJMVHIw9RnSJAGFl98adWe3NqE_DdM02PyHb23MoHqE_xd8z3eFhngyaMImhc4",</pre> |
| </div> |
| </div> |
| <div class="ulist"> |
| <ul> |
| <li> |
| <p>click Explore to load Swagger for WS Agent</p> |
| </li> |
| </ul> |
| </div> |
| <div class="imageblock"> |
| <div class="content"> |
| <img src="/che/docs/images/devel/swagger.png" alt="swagger"> |
| </div> |
| </div> |
| </div> |
| </div> |
| |
| <div class="tags"> |
| |
| <b>Tags: </b> |
| |
| |
| |
| <a href="tag_keycloak.html" class="btn btn-default navbar-btn cursorNorm" role="button">keycloak</a> |
| |
| |
| |
| </div> |
| |
| <!-- |
| --> |
| |
| </div> |
| |
| <hr class="shaded"/> |
| |
| <footer> |
| <div class="row"> |
| <div class="col-lg-12 footer"> |
| Eclipse Che - Documentation <br/> |
| Site last generated: Sep 13, 2018 <br/> |
| <hr> |
| <a href="http://www.eclipse.org" target="_blank">Eclipse Foundation</a><br/> |
| <a href="http://www.eclipse.org/legal/privacy.php" target="_blank">Privacy Policy</a><br/> |
| <a href="http://www.eclipse.org/legal/termsofuse.php" target="_blank">Terms of Use</a><br/> |
| <a href="https://www.eclipse.org/legal/epl-2.0/" target="_blank">Eclipse Public License</a><br/> |
| <a href="http://www.eclipse.org/legal" target="_blank">Legal Resources</a><br/> |
| </div> |
| </div> |
| </footer> |
| |
| |
| |
| |
| <!-- /.row --> |
| </div> |
| <!-- /.container --> |
| </div> |
| <!-- /#main --> |
| </div> |
| |
| </body> |
| |
| </html> |