Added base impl for OAuth-2
This commit is contained in:
		
							parent
							
								
									08ab9752fc
								
							
						
					
					
						commit
						7fc46010b7
					
				@ -132,6 +132,18 @@
 | 
			
		||||
            <groupId>org.springframework.boot</groupId>
 | 
			
		||||
            <artifactId>spring-boot-starter-websocket</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>org.springframework.cloud</groupId>
 | 
			
		||||
            <artifactId>spring-cloud-starter-oauth2</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>org.springframework.security</groupId>
 | 
			
		||||
            <artifactId>spring-security-oauth2-client</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>org.springframework.security</groupId>
 | 
			
		||||
            <artifactId>spring-security-oauth2-jose</artifactId>
 | 
			
		||||
        </dependency>
 | 
			
		||||
        <dependency>
 | 
			
		||||
            <groupId>io.jsonwebtoken</groupId>
 | 
			
		||||
            <artifactId>jjwt</artifactId>
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,81 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright © 2016-2020 The Thingsboard Authors
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
package org.thingsboard.server.config;
 | 
			
		||||
 | 
			
		||||
import org.springframework.beans.factory.annotation.Value;
 | 
			
		||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 | 
			
		||||
import org.springframework.context.annotation.Bean;
 | 
			
		||||
import org.springframework.context.annotation.Configuration;
 | 
			
		||||
import org.springframework.security.oauth2.client.registration.ClientRegistration;
 | 
			
		||||
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
 | 
			
		||||
import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository;
 | 
			
		||||
import org.springframework.security.oauth2.core.AuthorizationGrantType;
 | 
			
		||||
import org.springframework.security.oauth2.core.ClientAuthenticationMethod;
 | 
			
		||||
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
 | 
			
		||||
@ConditionalOnProperty(prefix = "security.oauth2", value = "enabled", havingValue = "true")
 | 
			
		||||
@Configuration
 | 
			
		||||
public class ThingsboardOAuth2Configuration {
 | 
			
		||||
 | 
			
		||||
    @Value("${security.oauth2.registrationId}")
 | 
			
		||||
    private String registrationId;
 | 
			
		||||
    @Value("${security.oauth2.userNameAttributeName}")
 | 
			
		||||
    private String userNameAttributeName;
 | 
			
		||||
 | 
			
		||||
    @Value("${security.oauth2.client.clientId}")
 | 
			
		||||
    private String clientId;
 | 
			
		||||
    @Value("${security.oauth2.client.clientName}")
 | 
			
		||||
    private String clientName;
 | 
			
		||||
    @Value("${security.oauth2.client.clientSecret}")
 | 
			
		||||
    private String clientSecret;
 | 
			
		||||
    @Value("${security.oauth2.client.accessTokenUri}")
 | 
			
		||||
    private String accessTokenUri;
 | 
			
		||||
    @Value("${security.oauth2.client.authorizationUri}")
 | 
			
		||||
    private String authorizationUri;
 | 
			
		||||
    @Value("${security.oauth2.client.redirectUriTemplate}")
 | 
			
		||||
    private String redirectUriTemplate;
 | 
			
		||||
    @Value("${security.oauth2.client.scope}")
 | 
			
		||||
    private String scope;
 | 
			
		||||
    @Value("${security.oauth2.client.jwkSetUri}")
 | 
			
		||||
    private String jwkSetUri;
 | 
			
		||||
    @Value("${security.oauth2.client.authorizationGrantType}")
 | 
			
		||||
    private String authorizationGrantType;
 | 
			
		||||
    @Value("${security.oauth2.client.clientAuthenticationMethod}")
 | 
			
		||||
    private String clientAuthenticationMethod;
 | 
			
		||||
 | 
			
		||||
    @Value("${security.oauth2.resource.userInfoUri}")
 | 
			
		||||
    private String userInfoUri;
 | 
			
		||||
 | 
			
		||||
    @Bean
 | 
			
		||||
    public ClientRegistrationRepository clientRegistrationRepository() {
 | 
			
		||||
        ClientRegistration registration = ClientRegistration.withRegistrationId(registrationId)
 | 
			
		||||
                .clientId(clientId)
 | 
			
		||||
                .authorizationUri(authorizationUri)
 | 
			
		||||
                .clientSecret(clientSecret)
 | 
			
		||||
                .tokenUri(accessTokenUri)
 | 
			
		||||
                .redirectUriTemplate(redirectUriTemplate)
 | 
			
		||||
                .scope(scope.split(","))
 | 
			
		||||
                .clientName(clientName)
 | 
			
		||||
                .authorizationGrantType(new AuthorizationGrantType(authorizationGrantType))
 | 
			
		||||
                .userInfoUri(userInfoUri)
 | 
			
		||||
                .userNameAttributeName(userNameAttributeName)
 | 
			
		||||
                .jwkSetUri(jwkSetUri)
 | 
			
		||||
                .clientAuthenticationMethod(new ClientAuthenticationMethod(clientAuthenticationMethod))
 | 
			
		||||
                .build();
 | 
			
		||||
        return new InMemoryClientRegistrationRepository(Collections.singletonList(registration));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -18,6 +18,8 @@ package org.thingsboard.server.config;
 | 
			
		||||
import com.fasterxml.jackson.databind.ObjectMapper;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Qualifier;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Required;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Value;
 | 
			
		||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
 | 
			
		||||
import org.springframework.boot.autoconfigure.security.SecurityProperties;
 | 
			
		||||
import org.springframework.context.annotation.Bean;
 | 
			
		||||
@ -73,12 +75,25 @@ public class ThingsboardSecurityConfiguration extends WebSecurityConfigurerAdapt
 | 
			
		||||
    public static final String WS_TOKEN_BASED_AUTH_ENTRY_POINT = "/api/ws/**";
 | 
			
		||||
 | 
			
		||||
    @Autowired private ThingsboardErrorResponseHandler restAccessDeniedHandler;
 | 
			
		||||
    @Autowired private AuthenticationSuccessHandler successHandler;
 | 
			
		||||
 | 
			
		||||
    @Autowired(required = false)
 | 
			
		||||
    @Qualifier("oauth2AuthenticationSuccessHandler")
 | 
			
		||||
    private AuthenticationSuccessHandler oauth2AuthenticationSuccessHandler;
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
    @Qualifier("defaultAuthenticationSuccessHandler")
 | 
			
		||||
    private AuthenticationSuccessHandler successHandler;
 | 
			
		||||
 | 
			
		||||
    @Autowired private AuthenticationFailureHandler failureHandler;
 | 
			
		||||
    @Autowired private RestAuthenticationProvider restAuthenticationProvider;
 | 
			
		||||
    @Autowired private JwtAuthenticationProvider jwtAuthenticationProvider;
 | 
			
		||||
    @Autowired private RefreshTokenAuthenticationProvider refreshTokenAuthenticationProvider;
 | 
			
		||||
 | 
			
		||||
    @Value("${security.oauth2.enabled}")
 | 
			
		||||
    private boolean oauth2Enabled;
 | 
			
		||||
    @Value("${security.oauth2.client.loginProcessingUrl}")
 | 
			
		||||
    private String loginProcessingUrl;
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
    @Qualifier("jwtHeaderTokenExtractor")
 | 
			
		||||
    private TokenExtractor jwtHeaderTokenExtractor;
 | 
			
		||||
@ -189,6 +204,11 @@ public class ThingsboardSecurityConfiguration extends WebSecurityConfigurerAdapt
 | 
			
		||||
                .addFilterBefore(buildRefreshTokenProcessingFilter(), UsernamePasswordAuthenticationFilter.class)
 | 
			
		||||
                .addFilterBefore(buildWsJwtTokenAuthenticationProcessingFilter(), UsernamePasswordAuthenticationFilter.class)
 | 
			
		||||
                .addFilterAfter(rateLimitProcessingFilter, UsernamePasswordAuthenticationFilter.class);
 | 
			
		||||
        if (oauth2Enabled) {
 | 
			
		||||
            http.oauth2Login()
 | 
			
		||||
                    .loginProcessingUrl(loginProcessingUrl)
 | 
			
		||||
                    .successHandler(oauth2AuthenticationSuccessHandler);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -0,0 +1,125 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright © 2016-2020 The Thingsboard Authors
 | 
			
		||||
 *
 | 
			
		||||
 * Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
 * you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 *
 | 
			
		||||
 *     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
 * See the License for the specific language governing permissions and
 | 
			
		||||
 * limitations under the License.
 | 
			
		||||
 */
 | 
			
		||||
package org.thingsboard.server.service.security.auth.oauth;
 | 
			
		||||
 | 
			
		||||
import com.fasterxml.jackson.databind.ObjectMapper;
 | 
			
		||||
import org.springframework.beans.factory.annotation.Autowired;
 | 
			
		||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 | 
			
		||||
import org.springframework.security.authentication.InsufficientAuthenticationException;
 | 
			
		||||
import org.springframework.security.authentication.LockedException;
 | 
			
		||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
 | 
			
		||||
import org.springframework.security.core.Authentication;
 | 
			
		||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
 | 
			
		||||
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
 | 
			
		||||
import org.springframework.stereotype.Component;
 | 
			
		||||
import org.thingsboard.server.common.data.User;
 | 
			
		||||
import org.thingsboard.server.common.data.id.TenantId;
 | 
			
		||||
import org.thingsboard.server.common.data.security.UserCredentials;
 | 
			
		||||
import org.thingsboard.server.dao.user.UserService;
 | 
			
		||||
import org.thingsboard.server.service.security.auth.jwt.RefreshTokenRepository;
 | 
			
		||||
import org.thingsboard.server.service.security.model.SecurityUser;
 | 
			
		||||
import org.thingsboard.server.service.security.model.UserPrincipal;
 | 
			
		||||
import org.thingsboard.server.service.security.model.token.JwtToken;
 | 
			
		||||
import org.thingsboard.server.service.security.model.token.JwtTokenFactory;
 | 
			
		||||
import org.thingsboard.server.service.security.system.SystemSecurityService;
 | 
			
		||||
 | 
			
		||||
import javax.servlet.ServletException;
 | 
			
		||||
import javax.servlet.http.HttpServletRequest;
 | 
			
		||||
import javax.servlet.http.HttpServletResponse;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
@Component(value="oauth2AuthenticationSuccessHandler")
 | 
			
		||||
@ConditionalOnProperty(prefix = "security.oauth2", value = "enabled", havingValue = "true")
 | 
			
		||||
public class Oauth2AuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
 | 
			
		||||
 | 
			
		||||
    private final ObjectMapper mapper;
 | 
			
		||||
    private final JwtTokenFactory tokenFactory;
 | 
			
		||||
    private final RefreshTokenRepository refreshTokenRepository;
 | 
			
		||||
    private final SystemSecurityService systemSecurityService;
 | 
			
		||||
    private final UserService userService;
 | 
			
		||||
 | 
			
		||||
    @Autowired
 | 
			
		||||
    public Oauth2AuthenticationSuccessHandler(final ObjectMapper mapper,
 | 
			
		||||
                                              final JwtTokenFactory tokenFactory,
 | 
			
		||||
                                              final RefreshTokenRepository refreshTokenRepository,
 | 
			
		||||
                                              final UserService userService,
 | 
			
		||||
                                              final SystemSecurityService systemSecurityService) {
 | 
			
		||||
        this.mapper = mapper;
 | 
			
		||||
        this.tokenFactory = tokenFactory;
 | 
			
		||||
        this.refreshTokenRepository = refreshTokenRepository;
 | 
			
		||||
        this.userService = userService;
 | 
			
		||||
        this.systemSecurityService = systemSecurityService;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
 | 
			
		||||
        Object object = authentication.getPrincipal();
 | 
			
		||||
 | 
			
		||||
        System.out.println(object);
 | 
			
		||||
 | 
			
		||||
        // active user check
 | 
			
		||||
 | 
			
		||||
        UserPrincipal principal = new UserPrincipal(UserPrincipal.Type.USER_NAME, "tenant@thingsboard.org");
 | 
			
		||||
        SecurityUser securityUser =  (SecurityUser) authenticateByUsernameAndPassword(principal,"tenant@thingsboard.org", "tenant").getPrincipal();
 | 
			
		||||
 | 
			
		||||
        JwtToken accessToken = tokenFactory.createAccessJwtToken(securityUser);
 | 
			
		||||
        JwtToken refreshToken = refreshTokenRepository.requestRefreshToken(securityUser);
 | 
			
		||||
 | 
			
		||||
        Map<String, String> tokenMap = new HashMap<String, String>();
 | 
			
		||||
        tokenMap.put("token", accessToken.getToken());
 | 
			
		||||
        tokenMap.put("refreshToken", refreshToken.getToken());
 | 
			
		||||
 | 
			
		||||
//        response.setStatus(HttpStatus.OK.value());
 | 
			
		||||
//        response.setContentType(MediaType.APPLICATION_JSON_VALUE);
 | 
			
		||||
//        mapper.writeValue(response.getWriter(), tokenMap);
 | 
			
		||||
 | 
			
		||||
        request.setAttribute("token", accessToken.getToken());
 | 
			
		||||
        response.addHeader("token", accessToken.getToken());
 | 
			
		||||
 | 
			
		||||
        getRedirectStrategy().sendRedirect(request, response, "http://localhost:4200/?accessToken=" + accessToken.getToken() + "&refreshToken=" + refreshToken.getToken());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private Authentication authenticateByUsernameAndPassword(UserPrincipal userPrincipal, String username, String password) {
 | 
			
		||||
        User user = userService.findUserByEmail(TenantId.SYS_TENANT_ID, username);
 | 
			
		||||
        if (user == null) {
 | 
			
		||||
            throw new UsernameNotFoundException("User not found: " + username);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
 | 
			
		||||
            UserCredentials userCredentials = userService.findUserCredentialsByUserId(TenantId.SYS_TENANT_ID, user.getId());
 | 
			
		||||
            if (userCredentials == null) {
 | 
			
		||||
                throw new UsernameNotFoundException("User credentials not found");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            try {
 | 
			
		||||
                systemSecurityService.validateUserCredentials(user.getTenantId(), userCredentials, username, password);
 | 
			
		||||
            } catch (LockedException e) {
 | 
			
		||||
                throw e;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (user.getAuthority() == null)
 | 
			
		||||
                throw new InsufficientAuthenticationException("User has no authority assigned");
 | 
			
		||||
 | 
			
		||||
            SecurityUser securityUser = new SecurityUser(user, userCredentials.isEnabled(), userPrincipal);
 | 
			
		||||
            return new UsernamePasswordAuthenticationToken(securityUser, null, securityUser.getAuthorities());
 | 
			
		||||
        } catch (Exception e) {
 | 
			
		||||
            throw e;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@ -36,7 +36,7 @@ import java.io.IOException;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
 | 
			
		||||
@Component
 | 
			
		||||
@Component(value="defaultAuthenticationSuccessHandler")
 | 
			
		||||
public class RestAwareAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
 | 
			
		||||
    private final ObjectMapper mapper;
 | 
			
		||||
    private final JwtTokenFactory tokenFactory;
 | 
			
		||||
 | 
			
		||||
@ -26,6 +26,7 @@
 | 
			
		||||
    </appender>
 | 
			
		||||
 | 
			
		||||
    <logger name="org.thingsboard.server" level="INFO" />
 | 
			
		||||
    <logger name="org.springframework.security" level="DEBUG" />
 | 
			
		||||
    <logger name="akka" level="INFO" />
 | 
			
		||||
 | 
			
		||||
<!--    <logger name="org.thingsboard.server.service.queue" level="TRACE" />-->
 | 
			
		||||
 | 
			
		||||
@ -97,6 +97,44 @@ security:
 | 
			
		||||
    allowClaimingByDefault: "${SECURITY_CLAIM_ALLOW_CLAIMING_BY_DEFAULT:true}"
 | 
			
		||||
    # Time allowed to claim the device in milliseconds
 | 
			
		||||
    duration: "${SECURITY_CLAIM_DURATION:60000}" # 1 minute, note this value must equal claimDevices.timeToLiveInMinutes value
 | 
			
		||||
  basic:
 | 
			
		||||
    enabled: false
 | 
			
		||||
    #  oauth2:
 | 
			
		||||
    #    enabled: true
 | 
			
		||||
    #    registrationId: A
 | 
			
		||||
    #    userNameAttributeName: email
 | 
			
		||||
    #    client:
 | 
			
		||||
    #      clientName: Thingsboard Dev Test Q
 | 
			
		||||
    #      clientId: 5f5c0998-1d9b-4679-9610-6108fb91af2a
 | 
			
		||||
    #      clientSecret: h_kXVb7Ee1LgDDinix_nkAh_owWX7YCO783NNteF9AIOqlTWu2L03YoFjv5KL8yRVyx4uYAE-r_N3tFbupE8Kw
 | 
			
		||||
    #      accessTokenUri: https://federation-q.auth.schwarz/nidp/oauth/nam/token
 | 
			
		||||
    #      authorizationUri: https://federation-q.auth.schwarz/nidp/oauth/nam/authz
 | 
			
		||||
    #      scope: openid,profile,email,siam
 | 
			
		||||
    #      redirectUriTemplate: http://localhost:8080/login/oauth2/code/
 | 
			
		||||
    #      loginProcessingUrl: /login/oauth2/code/
 | 
			
		||||
    #      jwkSetUri: https://federation-q.auth.schwarz/nidp/oauth/nam/keys
 | 
			
		||||
    #      authorizationGrantType: authorization_code  # authorization_code, implicit, refresh_token, client_credentials
 | 
			
		||||
    #      clientAuthenticationMethod: post # basic, post
 | 
			
		||||
    #    resource:
 | 
			
		||||
    #      userInfoUri: https://federation-q.auth.schwarz/nidp/oauth/nam/userinfo
 | 
			
		||||
    oauth2:
 | 
			
		||||
      enabled: true
 | 
			
		||||
      registrationId: A
 | 
			
		||||
      userNameAttributeName: email
 | 
			
		||||
      client:
 | 
			
		||||
        clientName: Test app
 | 
			
		||||
        clientId: dVH9reqyqiXIG7M2wmamb0ySue8zaM4g
 | 
			
		||||
        clientSecret: EYAfAGxwkwoeYnb2o2cDgaWZB5k97OStpZQPPvcMMD-SVH2BuughTGeBazXtF5I6
 | 
			
		||||
        accessTokenUri: https://dev-r9m8ht0k.auth0.com/oauth/token
 | 
			
		||||
        authorizationUri: https://dev-r9m8ht0k.auth0.com/authorize
 | 
			
		||||
        scope: openid,profile,email
 | 
			
		||||
        redirectUriTemplate: http://localhost:8080/login/oauth2/code/
 | 
			
		||||
        loginProcessingUrl: /login/oauth2/code/
 | 
			
		||||
        jwkSetUri: https://dev-r9m8ht0k.auth0.com/.well-known/jwks.json
 | 
			
		||||
        authorizationGrantType: authorization_code  # authorization_code, implicit, refresh_token, client_credentials
 | 
			
		||||
        clientAuthenticationMethod: post # basic, post
 | 
			
		||||
      resource:
 | 
			
		||||
        userInfoUri: https://dev-r9m8ht0k.auth0.com/userinfo
 | 
			
		||||
 | 
			
		||||
# Dashboard parameters
 | 
			
		||||
dashboard:
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										15
									
								
								pom.xml
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								pom.xml
									
									
									
									
									
								
							@ -458,6 +458,21 @@
 | 
			
		||||
                <artifactId>spring-boot-starter-security</artifactId>
 | 
			
		||||
                <version>${spring-boot.version}</version>
 | 
			
		||||
            </dependency>
 | 
			
		||||
            <dependency>
 | 
			
		||||
                <groupId>org.springframework.cloud</groupId>
 | 
			
		||||
                <artifactId>spring-cloud-starter-oauth2</artifactId>
 | 
			
		||||
                <version>${spring-boot.version}</version>
 | 
			
		||||
            </dependency>
 | 
			
		||||
            <dependency>
 | 
			
		||||
                <groupId>org.springframework.security</groupId>
 | 
			
		||||
                <artifactId>spring-security-oauth2-client</artifactId>
 | 
			
		||||
                <version>${spring.version}</version>
 | 
			
		||||
            </dependency>
 | 
			
		||||
            <dependency>
 | 
			
		||||
                <groupId>org.springframework.security</groupId>
 | 
			
		||||
                <artifactId>spring-security-oauth2-jose</artifactId>
 | 
			
		||||
                <version>${spring.version}</version>
 | 
			
		||||
            </dependency>
 | 
			
		||||
            <dependency>
 | 
			
		||||
                <groupId>org.springframework.boot</groupId>
 | 
			
		||||
                <artifactId>spring-boot-starter-web</artifactId>
 | 
			
		||||
 | 
			
		||||
@ -47,6 +47,7 @@
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <md-button class="md-raised" type="submit">{{ 'login.login' | translate }}</md-button>
 | 
			
		||||
                    <a  href="oauth2/authorization/A">OAUTH2 LOGIN</a>
 | 
			
		||||
                </div>
 | 
			
		||||
            </form>
 | 
			
		||||
        </md-card-content>
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user