Using Basic auth with OAuth2 and JHipster - authentication

we use jhipster to generate gateway and microservices with OAuth2 authentication, and that works fine with a JHipster Registry and a Keycloak server. But we have a microservice that will be called from an external service, and this service use basic authentication.
So, on the gateway, we need to send login and pasword from basic auth to keycloak server, and use access token to call our service. I get access token by adding filter in MicroserviceSecurityConfiguration class :
http.addFilterBefore(basicAuthFilter, UsernamePasswordAuthenticationFilter.class);
And here a extract of filter method :
ResourceOwnerPasswordResourceDetails details = new ResourceOwnerPasswordResourceDetails();
details.setAccessTokenUri("http://keycloakserver/auth/realms/jhipster/protocol/openid-connect/token");
details.setGrantType("password");
details.setClientId("clientId");
details.setClientAuthenticationScheme(AuthenticationScheme.form);
details.setUsername(login);
details.setPassword(password);
AccessTokenRequest tokenRequest = new DefaultAccessTokenRequest();
ResourceOwnerPasswordAccessTokenProvider provider = new ResourceOwnerPasswordAccessTokenProvider();
OAuth2AccessToken accessToken = provider.obtainAccessToken(details, tokenRequest);
I guess I have to store this token in tokenStore, but I don't know how. So my questions are how use this token, and does the the way I get it is correct ?
Thanks for your help !

I Have same problem with you in my production system, then I changed Authentication server to JHipster UAA server, and problem is resolved.
I think you are using first kind now:
OAuth 2.0 / OIDC Authentication:
this uses an OpenID Connect server, like Keycloak or Okta, which handles authentication outside of the application.
Authentication with JHipster UAA server:
this uses a JHipster UAA server that must be generated separately, and which is an OAuth2 server that handles authentication outside of the application.

After some tests and trial and error, I managed to do that I want.
First, I created a BasicAuthenticationFilter class :
#Configuration
public class BasicAuthenticationFilter implements Filter {
private static final String GRANT_TYPE = "password";
private static final String BASIC_AUTH_HEADER = "Authorization";
private static final String BASIC_PREFIX = "Basic ";
#Value("${security.oauth2.client.access-token-uri}")
private String accessTokenUri;
#Value("${security.oauth2.client.client-id}")
private String clientId;
#Value("${security.oauth2.client.client-secret}")
private String clientSecret;
#Autowired
private TokenStore tokenStore;
private ResourceOwnerPasswordAccessTokenProvider provider;
public BasicAuthenticationFilter( ) {
provider = new ResourceOwnerPasswordAccessTokenProvider();
}
#Override
public void init(FilterConfig filterConfig) throws ServletException {
}
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
String header = null;
if (request instanceof HttpServletRequest) {
HttpServletRequest httpRequest = (HttpServletRequest) request;
header = httpRequest.getHeader(BASIC_AUTH_HEADER);
if (header != null && header.startsWith(BASIC_PREFIX)) {
String base64 = header.substring(BASIC_PREFIX.length());
String loginPassword = new String(Base64.getDecoder().decode(base64.getBytes()));
String[] split = loginPassword.split(":");
String login = split[0];
String password = split[1];
authenticate(httpRequest, login, password);
}
}
chain.doFilter(request, response);
}
private void authenticate(HttpServletRequest httpRequest, String login, String password) {
ResourceOwnerPasswordResourceDetails details = new ResourceOwnerPasswordResourceDetails();
details.setAccessTokenUri(accessTokenUri);
details.setGrantType(GRANT_TYPE);
details.setClientId(clientId);
details.setClientAuthenticationScheme(AuthenticationScheme.query);
details.setUsername(login);
details.setPassword(password);
DefaultAccessTokenRequest tokenRequest = new DefaultAccessTokenRequest();
tokenRequest.setCurrentUri(httpRequest.getRequestURI());
try {
OAuth2AccessToken accessToken = provider.obtainAccessToken(details, tokenRequest);
OAuth2Authentication oauth2Authentication = tokenStore.readAuthentication(accessToken);
AccessTokenDetails accessTokenDetail = new AccessTokenDetails(accessToken.getValue());
oauth2Authentication.setDetails(accessTokenDetail);
SecurityContext context = SecurityContextHolder.getContext();
context.setAuthentication(oauth2Authentication);
} catch (OAuth2AccessDeniedException e) {
throw new AccessDeniedException("Wrong credentials !");
}
}
#Override
public void destroy() {
}
public static class AccessTokenDetails {
private static final String DEFAULT_TOKEN_TYPE = "bearer";
public final String tokenType;
public final String tokenValue;
public AccessTokenDetails(String tokenValue) {
this(DEFAULT_TOKEN_TYPE, tokenValue);
}
public AccessTokenDetails(String tokenType, String tokenValue) {
this.tokenType = tokenType;
this.tokenValue = tokenValue;
}
}
}
This filter check if there are basic authentication, and if yes, authenticate user. The authentication details are stored in internal class AccessTokenDetails. So, the token can be read in AuthorizationHeaderUtil :
public class AuthorizationHeaderUtil {
public static String getAuthorizationHeader() {
SecurityContext context = SecurityContextHolder.getContext();
Authentication authentication = context.getAuthentication();
Object details = authentication.getDetails();
String tokenType = "";
String tokenValue = "";
if (details instanceof OAuth2AuthenticationDetails) {
OAuth2AuthenticationDetails oauth2Details = (OAuth2AuthenticationDetails) details;
tokenType = oauth2Details.getTokenType();
tokenValue = oauth2Details.getTokenValue();
} else if (details instanceof AccessTokenDetails) {
AccessTokenDetails accessTokenDetails = (AccessTokenDetails) details;
tokenType = accessTokenDetails.tokenType;
tokenValue = accessTokenDetails.tokenValue;
}
return String.format("%s %s", tokenType, tokenValue);
}
}
This class has been generated by JHipster, I add a check for the two authentication detail class I use.
I hope that will be useful.
Denis

Related

AAD authentication getting access token

I am trying to get an access token for powerbi users, following this link - https://learn.microsoft.com/en-us/power-bi/developer/automation/walkthrough-push-data-get-token
But I am getting an error at this line of code
var token = authContext.AcquireTokenAsync(resourceUri, clientID, new Uri(redirectUri)).Result.AccessToken;
Error:
clinetID is - cannot convert from 'string' to 'microsoft.identitymodel.clients.activedirectory.clientcredential'
new Uri(redirectUri) = cannot convert from 'System.uri' to 'microsoft.identitymodel.clients.activedirectory.User'
Code for getting access token:
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System;
using System.Threading.Tasks;
namespace Service
{
public class PowerbiService
{
private static string token = string.Empty;
static void Main(string[] args)
{
//Get an authentication access token
token = GetToken();
}
#region Get an authentication access token
private static async Task<string> GetToken()
{
string clientID = "{Client_ID}";
string redirectUri = "https://login.live.com/oauth20_desktop.srf";
string resourceUri = "https://analysis.windows.net/powerbi/api";
string authorityUri = "https://login.microsoftonline.net/common/";
AuthenticationContext authContext = new AuthenticationContext(authorityUri);
var token = authContext.AcquireTokenAsync(resourceUri, clientID, new Uri(redirectUri)).Result.AccessToken;
Console.WriteLine(token);
Console.ReadLine();
return token;
}
#endregion
}
}

How to use SoapCore in Asp.net Core project for exposing wsdl at project route folder

Your project, written with Asp.net Core, makes deploying Rest API. However, your customer wanted to communicate with soap. How to make an improvement
SoapCore has already done many things for us to support this situation. We apply step-by-step changes to our Asp.net Core project.
First in Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
try
{
services.AddSoapServiceOperationTuner(new MyServiceOperationTuner());
services.Configure<XApiSettings>(options =>
{
options.baseurl = XApiOptions[nameof(XApi.baseurl)];
options.accesstokenroute = XApiOptions[nameof(XApi.accesstokenroute)];
options.secret = XApiOptions[nameof(XApi.secret)];
options.secretkey = XApiOptions[nameof(XApi.secretkey)];
options.grant_type = XApiOptions[nameof(XApi.grant_type)];
options.username = XApiOptions[nameof(XApi.username)];
options.password = XApiOptions[nameof(XApi.password)];
});
services.AddSoapCore();
services.AddSingleton<IRESAdapterService>(new RESAdapterService(
Xcontroller: new XApiController(
services.BuildServiceProvider().GetRequiredService<IOptions<XApi>>(),
_corendonLogger
)));
services.AddSoapExceptionTransformer((ex) => ex.Message);
}
catch (Exception ex)
{
Log.Logger.Error("ConfigureServices Message: " + ex.Message);
}
}
If you want your application to be accessible from the root directory at the address you deploy, you can type path '/' directly or name it as '/ XX'
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, ApplicationContext dbContext)
{
try
{
app.UseSoapEndpoint<IRESAdapterService>(path: "/", binding: new BasicHttpBinding(), SoapSerializer.XmlSerializer);
}
}
In the case of requests that are handled on the server side, data sent as xml will normally be null. We need to make the following improvement in SoapCore so that the server can resolve the request.
public class MyServiceOperationTuner : IServiceOperationTuner
{
public void Tune(HttpContext httpContext, object serviceInstance, SoapCore.OperationDescription operation)
{
RESAdapterService service = serviceInstance as RESAdapterService;
service.SetHttpRequest = httpContext.Request;
}
}
In addition, the interface to meet the incoming requests and services to make redirects to our controller should write as follows
[ServiceContract]
public interface IRESAdapterService
{
[OperationContract]
[XmlSerializerFormat(SupportFaults = true)]
Task<OTA_AirAvailRS> getAvailability([FromBody]HttpRequestMessage req);
[OperationContract]
Task<OTA_AirPriceRS> pricing([FromBody]HttpRequestMessage req);
}
public class RESAdapterService : IRESAdapterService
{
XApiController _controller;
public HttpRequest SetHttpRequest { get; set; }
public RESAdapterService(XApiController XApi)
{
_controller = XApi;
}
public Task<MyRequesterClass> Method1([FromBody]HttpRequestMessage req)
{
return _controller.Method1(SetHttpRequest);
}
public Task<MyDiffRequesterClass> Method2([FromBody]HttpRequestMessage req)
{
return _controller. Method2(SetHttpRequest);
}
}
The controller was catching requests from the Request object, but; now the Request object has to get through the router service for the future of null in this context. Therefore we can implement the code that reads XML as follows
Stream reqBody = Request?.Body;
if (Request == null)
reqBody = (MyRequesterClass as HttpRequest).Body;
Let's come to the client side, write a simple framework console project
Normally we offer wsdl visual studio add references by adding the portion of the proxy can create and walk. (Recommended case) But in my case I decided to post xml with webclient because I use a user certificate and I don't know the type of object to send. Sample use below:
static string xml = " <ReqObj xmlns='http://tempuri.org/'>"
+ "</ ReqObj >";
static string wrapbody = #"<?xml version=""1.0"" encoding=""utf-8""?>
<soap:Envelope xmlns:soap=""http://schemas.xmlsoap.org/soap/envelope/""
xmlns:xsi=""http://www.w3.org/2001/XMLSchema-instance""
xmlns:xsd=""http://www.w3.org/2001/XMLSchema"">
<soap:Body>
#
</soap:Body>
</soap:Envelope>";
public static async Task<string> CreateSoapEnvelope()
{
HttpResponseMessage response = await PostXmlRequest("https://localhostorliveaddress.com");
string content = await response.Content.ReadAsStringAsync();
return content;
}
public static async Task<HttpResponseMessage> PostXmlRequest(string baseUrl)
{
X509Certificate2 clientCert = new X509Certificate2(#"D:\ccer\xxx.pfx", "password");
//X509Certificate2 clientCert = GetClientCertificate();
WebRequestHandler requestHandler = new WebRequestHandler();
requestHandler.ClientCertificates.Add(clientCert);
using (var httpClient = new HttpClient(requestHandler))
{
string wrpXmlContent = wrapbody.Replace("#", xml);
var httpContent = new StringContent(wrpXmlContent, Encoding.UTF8, "text/xml");
httpContent.Headers.Add("SOAPAction", "https://localhostorliveaddress.com/method1");
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("text/xml"));
return await httpClient.PostAsync(baseUrl, httpContent);
}
}
Getting Client certificate from My User Personel Store
private static X509Certificate2 GetClientCertificate()
{
X509Store userCaStore = new X509Store(StoreName.My, StoreLocation.CurrentUser);
try
{
userCaStore.Open(OpenFlags.ReadOnly);
X509Certificate2Collection certificatesInStore = userCaStore.Certificates;
X509Certificate2Collection findResult = certificatesInStore.
Find(X509FindType.FindBySubjectName, "XRootCertificateOnMyUserPersonelStore", true);
X509Certificate2 clientCertificate = null;
if (findResult.Count == 1)
{
clientCertificate = findResult[0];
}
else
{
throw new Exception("Unable to locate the correct client certificate.");
}
return clientCertificate;
}
catch
{
throw;
}
finally
{
userCaStore.Close();
}
}

Spring-security/Grails app - Custom WebSecurity configurations not getting called

My project is based on Grail 2.5.6 and Spring plugins. I'm trying to create a custom auth provider, filter and token extending their respective basic classes.
this.getAuthenticationManager().authenticate(authRequest)
In my filter the authentication manager is always null. So, it throws cannot invoke authenticate() on a null object. When I debug on the authenticationManager, it lists other provider names but my custom one.
Here is my custom web security config
#Configuration
#EnableGlobalMethodSecurity(securedEnabled=true)
public class CustomWebSecurityConfig extends WebSecurityConfigurerAdapter {
OrbisAuthenticationProvider orbisAuthenticationProvider
public CustomWebSecurityConfig() {
super()
log.debug "configure custom security"
print("configure custom security")
}
#Autowired
protected void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
print("configure method 1")
log.debug "configure method 1"
auth.authenticationProvider(orbisAuthenticationProvider)
}
#Bean(name= BeanIds.AUTHENTICATION_MANAGER)
#Override
AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean()
}
#Bean
OrbisAuthenticationFilter orbisAuthenticationProvider() throws Exception {
log.debug "orbis Authentication provider"
OrbisAuthenticationProvider orbisAuthenticationProvider = new OrbisAuthenticationProvider(authenticationManagerBean())
return orbisAuthenticationProvider
}
#Bean
#Autowired
public OrbisAuthenticationFilter orbisAuthenticationFilter() throws Exception {
print("configure orbis filtr")
OrbisAuthenticationFilter oaf = new OrbisAuthenticationFilter()
oaf.setAuthenticationManager(authenticationManagerBean())
oaf.setFilterProcessesUrl("j_orbis_security_check")
oaf.setUsernameParameter("email")
oaf.setPasswordParameter("password")
oaf.setAuthenticationSuccessHandler(new SavedRequestAwareAuthenticationSuccessHandler()
.setDefaultTargetUrl("/oauth/authorize"))
oaf.setAuthenticationFailureHandler(new SimpleUrlAuthenticationFailureHandler()
.setDefaultFailureUrl("/loginWithOrbis"))
oaf.afterPropertiesSet()
return oaf
}
}
On debugging, it doesn't look like any of these methods are getting called. The annotations don't seem enough to get picked up. I had tried #ComponentScan too.
Do I have to inject this security config somewhere? How do I get authManager to be available in my filter?
OrbisAuthFilter
class OrbisAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
// #Autowired
OrbisAuthenticationProvider orbisAuthenticationProvider
OrbisAuthenticationFilter() {
super("/j_orbis_security_check")
orbisAuthenticationProvider = new OrbisAuthenticationProvider()
}
void afterPropertiesSet() {
assert authenticationManager != null, 'authenticationManager must be specified'
}
#Override
Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
String username = request.getParameter("email")
String password = request.getParameter("password")
String accessCode = request.getParameter("accessCode")
OrbisAuthenticationToken authRequestForAuthentication = new OrbisAuthenticationToken(username, password, accessCode)
// This throws error because getAuthenticationManager returns null
// authRequestForAuthentication = this.getAuthenticationManager.authenticate(authRequestForAuthentication)
//This works if I instantiate the orbis provider object in the constructor
authRequestForAuthentication = this.orbisAuthenticationProvider.authenticate(authRequestForAuthentication)
SecurityContextHolder.getContext().setAuthentication(authRequestForAuthentication)
return authRequestForAuthentication
}
protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) {
authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request));
}
#Override
#Autowired
public void setAuthenticationManager(AuthenticationManager authenticationManager) {
super.setAuthenticationManager(authenticationManager);
}
}
OrbisAuthProvider
class OrbisAuthenticationProvider implements AuthenticationProvider {
#Override
Authentication authenticate(Authentication authentication) throws AuthenticationException {
OrbisAuthenticationToken orbisAuth = (OrbisAuthenticationToken) authentication
String username = orbisAuth.principal
String password = orbisAuth.credentials
String orbisAccessCode = orbisAuth.orbisAccessCode
def urlToUse = 'https://coopstatus.neu.edu/sail_api/full.aspx?' + 'ac=' + orbisAccessCode + '&e='+ username + '&p=' + password
HttpClient httpClient = DefaultHttpClient.newInstance()
HttpGet getRequest = new HttpGet(urlToUse)
HttpResponse httpResponse = httpClient.execute(getRequest)
JSONObject orbisResponse = new JSONObject(httpResponse.getEntity().getContent().getText())
// if(orbisResponse.get("IsFound")) {
// //Return error not authenticated
// }
Collection<GrantedAuthority> orbisUserGrantedAuthorities = getLDAPUserAuthorities(orbisResponse.get("Email"))
orbisAuth = new OrbisAuthenticationToken(username, password, orbisAccessCode, orbisUserGrantedAuthorities)
return orbisAuth
}
private Collection<GrantedAuthority> getLDAPUserAuthorities(String username) {
LDAPUserDetails currentLdapUserDetails
try {
currentLdapUserDetails = new LDAPUserDetailsService().loadUserByOrbisUsername(username)
log.debug currentLdapUserDetails
} catch(org.springframework.security.core.userdetails.UsernameNotFoundException e) {
log.error("User " + username + " not found in ldap", e)
}
Collection<GrantedAuthority> authorities = new ArrayList<>()
for (String authority : currentLdapUserDetails.authorities) {
authorities.add(new SimpleGrantedAuthority(authority))
}
return authorities
}
#Override
public boolean supports(Class<?> authentication) {
return (OrbisAuthenticationToken.class
.isAssignableFrom(authentication));
}
}
Resources.groovy
import edu.neu.security.OrbisAuthenticationFilter
import edu.neu.security.OrbisAuthenticationProvider
beans = {
userDetailsService(edu.neu.security.LDAPUserDetailsService)
orbisAuthenticationProvider(OrbisAuthenticationProvider)
orbisAuthenticationFilter(OrbisAuthenticationFilter) {
orbisAuthenticationProvider = ref("orbisAuthenticationProvider")
requiresAuthenticationRequestMatcher = ref('filterProcessUrlRequestMatcher')
// This throws error during startup. Unable to init bean
// authenicationManager = ref("authenicationManager")
}
myOAuth2ProviderFilter(OAuth2ProviderFilters) {
//grailsApplication = ref('grailsApplication')
// properties
}
}
I followed some of the concepts from this project: https://github.com/ppazos/cabolabs-ehrserver/
Even if the whole process is executed and securityContext is set with authenticated, when I hit oauth/authorize to get Authorization_Code, it redirects back to '/login/auth'. It still doesn't know that a user is already authenticated.
When you add an authentication provider to the AuthenticationManagerBuilder bean (which comes from AuthenticationConfiguration), the authentication manager bean you declare is not used.
Try:
#Configuration
#EnableGlobalMethodSecurity(securedEnabled=true)
public class CustomWebSecurityConfig {
OrbisAuthenticationProvider lwoAuthProvider;
public CustomWebSecurityConfig() {
//
}
#Bean(name= BeanIds.AUTHENTICATION_MANAGER)
AuthenticationManager authenticationManagerBean() throws Exception {
return new ProviderManager(Arrays.asList(lwoAuthProvider));
}
Your AuthenticationManager bean should get picked up and will be used for method security. You can also #Autowire it in your filter if it is being managed by Spring, or #Autowire it in the #Configuration class that instantiates your filter.
NOTE: the above class WILL NOT create any of the Spring Security filters.
(The filter chain wasn't being created anyway - you didn't annotate your class with #EnableWebSecurity)

Using Dropwizard Authentication manual

I'm currently using http://www.dropwizard.io/1.1.0/docs/manual/auth.html# Dropwizard-Authentication in my Application. But i like to do the authentication "manualy" which means from a specific login/logout API call on a not authenticated REST interface.
Is there any possibility to forward an REST Call to the Authentication?
#POST
#Path("login")
#Consumes(MediaType.APPLICATION_JSON)
#Timed
#UnitOfWork
public Optional<LoginResponse> login(LoginRequest request) {
// TODO forward login request to authentication
return null;
}
Thx in advance
Thx for helping me. I found a solution like that:
Adding an Authenticator to the REST Client
client = ClientBuilder.newClient();
authenticator = new Authenticator();
client.register(authenticator);
Setup the Authenticator on Login-Successfull
final UserAPIResponse response = create(request, UserAPI.PATH_ATTRIBUTE_DEFINITION_LOGIN);
if (response == null || response.isFailed()) {
connector.setupAuthenticator(null, null);
} else {
connector.setupAuthenticator(request.getUsername(), request.getPassword());
}
And here is the Authenticator
class Authenticator implements ClientRequestFilter {
#Override
public void filter(ClientRequestContext requestContext) throws IOException {
final MultivaluedMap<String, Object> headers = requestContext.getHeaders();
final String basicAuthentication = getBasicAuthentication();
if (basicAuthentication == null) return;
headers.add("Authorization", basicAuthentication);
}
void setup(String username, String password) {
this.user = username;
this.password = password;
}
private String getBasicAuthentication() {
if (user == null || password == null) return null;
final String token = this.user + ":" + this.password;
try {
return "BASIC " + DatatypeConverter.printBase64Binary(token.getBytes("UTF-8"));
} catch (final UnsupportedEncodingException ex) {
throw new IllegalStateException("Cannot encode with UTF-8", ex);
}
}
private String password;
private String user;
}
on the server side i have an Authenticator
public class UserAuthenticator implements Authenticator<BasicCredentials, User> {
UserAuthenticator(UserDAO userDAO) {
this.userDAO = userDAO;
}
#UnitOfWork
#Override
public Optional<User> authenticate(BasicCredentials credentials) throws AuthenticationException {
final String username = credentials.getUsername();
final Optional<DbUser> result = userDAO.getByName(username);
if (!result.isPresent()) return Optional.empty();
final DbUser user = result.get();
final String password = credentials.getPassword();
if (!StringUtils.equals(password, user.getPassword())) return Optional.empty();
if (!user.isOnline()) return Optional.empty();
user.handleAction();
userDAO.save(user);
return Optional.of(UserMgr.convert(user));
}
private final UserDAO userDAO;
}
And to get em working correctly:
SessionDao dao = new SessionDao(hibernateBundle.getSessionFactory());
ExampleAuthenticator exampleAuthenticator = new UnitOfWorkAwareProxyFactory(hibernateBundle)
.create(ExampleAuthenticator.class, SessionDao.class, dao);
So finally there is one REST-Call to login the User and the authentication is done on the result by the client automatically.

How to use/Implement OAuth2 with Owin in ASp.net Core?

Hello I am very beginner in whole web development , I got a task to make an API and for the good or bad of it I chose Asp.Core to do it .
The api connects a mobile client with a CRM system and there is an AD system (Not azure nor windows AD) it is called NetIQ. Any request to the api has to be from a user who is authenticated by Net IQ before then the API issues a token to the client.
Anyway I would like to have kind of authentication mechanism, and I have been told that OWIN can handle OAUTh2 stuff .
I have the exact code that I need , but it is with MVC 5.
Can someone help me with migrating this thing to MVC core ?
I searched for long time and could not find what I want . Maybe because i am still a bigenner in the web stuff area .
The code that I want to migrate is
Startup.cs
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
}
}
Startup.Auth.cs
public partial class Startup
{
public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; }
public static string PublicClientId { get; private set; }
// For more information on configuring authentication, please visit http://go.microsoft.com/fwlink/?LinkId=301864
public void ConfigureAuth(IAppBuilder app)
{
// Configure the application for OAuth based flow
PublicClientId = "self";
OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/token"),
Provider = new ApplicationOAuthProvider(),
AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(15),
AllowInsecureHttp = true
};
// Enable the application to use bearer tokens to authenticate users
app.UseOAuthBearerTokens(OAuthOptions);
}
}
ApplicationOAuthProvider.cs
public class ApplicationOAuthProvider : OAuthAuthorizationServerProvider
{
private static string aadInstance = "https://login.microsoftonline.com/{0}";
private static string tenant = ConfigurationManager.AppSettings["AzureAD.Tenant"];
private static string clientId = ConfigurationManager.AppSettings["AzureAD.ClientId"];
private static string authority = string.Format(CultureInfo.InvariantCulture, aadInstance, tenant);
private static AuthenticationContext authContext = null;
public override async Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
context.Validated();
}
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
authContext = new AuthenticationContext(authority, new TokenCache());
var creds = new UserPasswordCredential(context.UserName, context.Password);
AuthenticationResult result;
try
{
result = await authContext.AcquireTokenAsync(clientId, clientId, creds);
}
catch (Exception ex)
{
context.SetError("invalid_grant", "The user name or password is incorrect.");
return;
}
var identity = new ClaimsIdentity(context.Options.AuthenticationType);
identity.AddClaim(new Claim("sub", context.UserName));
identity.AddClaim(new Claim("role", "user"));
identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName));
context.Validated(identity);
}
}
So have anyone a sample how would I do that in ASP core ? because the whole startup thing is making me confused to be honest .