Asp.net OpenID Identity Server specifying scope causes error - asp.net

I have an ASP.Net web form site that I want to authenticate with Identity Server 3. In the Identity Server app, I have a list of Scopes defined (one of which is "email"). But, when I run my code and attempt to authenticate, I get an error. If I remove the Scope property, it runs fine, but does not include the Scope fields I requested (only has generic claims). Here is my code:
Public Sub ConfigureAuth(app As IAppBuilder)
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap = New Dictionary(Of String, String)
app.UseCookieAuthentication(New CookieAuthenticationOptions() With {
.AuthenticationType = "Cookies"
})
Dim OpenIdAuthOption = New OpenIdConnectAuthenticationOptions() With {
.Authority = "https://myidentityserver.azurewebsites.net/core/",
.ClientId = "adfasdfafasdfasfasf",
.RedirectUri = "https://localhost:44321/default.aspx/",
.ResponseType = OpenIdConnectResponseType.IdTokenToken,
.SignInAsAuthenticationType = "Cookies",
.Scope = "email",
.Notifications = New OpenIdConnectAuthenticationNotifications() With {
.SecurityTokenReceived = Function(ctx)
Return Task.FromResult(0)
End Function,
.MessageReceived = Function(ctx)
Return Task.FromResult(0)
End Function,
.SecurityTokenValidated = Function(ctx)
Dim claimPrincipal = ctx.AuthenticationTicket.Identity
TransformClaims(claimPrincipal)
Return Task.FromResult(0)
End Function,
.AuthorizationCodeReceived = Function(ctx)
Return Task.FromResult(0)
End Function,
.RedirectToIdentityProvider = Function(context)
RedirectLogin(context)
Return Task.FromResult(0)
End Function
}
}
app.UseOpenIdConnectAuthentication(OpenIdAuthOption)
End Sub
The error I get is:
"OpenIdConnectMessage.Error was not null, indicating an error. Error:
'invalid_request'. Error_Description (may be empty): ''. Error_Uri
(may be empty): ''."
can anyone explain how I can get the scope values (like "email) from Identity Server?

In the scope of your client configuration add openid as well it is mandatory scope to be there if you use response type (IdTokenToken/CodeIdToken/CodeToken/CodeIdTokenToken)
You code should be like
Dim OpenIdAuthOption = New OpenIdConnectAuthenticationOptions() With {
.Authority = "https://myidentityserver.azurewebsites.net/core/",
.ClientId = "adfasdfafasdfasfasf",
.RedirectUri = "https://localhost:44321/default.aspx/",
.ResponseType = OpenIdConnectResponseType.IdTokenToken,
.SignInAsAuthenticationType = "Cookies",
.Scope = "openid email",
.Notifications = New OpenIdConnectAuthenticationNotifications() With {
.SecurityTokenReceived = Function(ctx)
Return Task.FromResult(0)
End Function,
.MessageReceived = Function(ctx)
Return Task.FromResult(0)
End Function,
.SecurityTokenValidated = Function(ctx)
Dim claimPrincipal = ctx.AuthenticationTicket.Identity
TransformClaims(claimPrincipal)
Return Task.FromResult(0)
End Function,
.AuthorizationCodeReceived = Function(ctx)
Return Task.FromResult(0)
End Function,
.RedirectToIdentityProvider = Function(context)
RedirectLogin(context)
Return Task.FromResult(0)
End Function
}
}

Related

ASP.net IdentiyServer 3 AuthorizationCodeReceived not firing

when a user authenticates with Identity Server 3, AuthorizationCodeReceived never fires. RedirectToIdentityProvider does get fired but thats it. I am trying to call a function that will get the users email or windows ID, and then add a custom claim. But without the AuthorizationCodeReceived method being called, I am not sure how to do that. Anyone have experience with this? Not sure if it matters, but my code is ASP.net windows form (not MVC)
Here is my code:
Public Sub ConfigureAuth(app As IAppBuilder)
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap = New Dictionary(Of String, String)
app.UseCookieAuthentication(New CookieAuthenticationOptions() With {
.AuthenticationType = CookieAuthenticationDefaults.AuthenticationType
})
Dim OpenIdAuthOption = New OpenIdConnectAuthenticationOptions() With {
.Authority = "https://myidentityserver.azurewebsites.net/core/",
.ClientId = "adfafasfasdfa",
.RedirectUri = "https://localhost:44321/default.aspx/",
.ResponseType = ("access_token"),
.RequireHttpsMetadata = False,
.SignInAsAuthenticationType = "Cookies",
.Notifications = New OpenIdConnectAuthenticationNotifications() With {
.AuthorizationCodeReceived = Function(ctx)
Dim claimPrincipal As ClaimsPrincipal = ctx.AuthenticationTicket.Identity.Claims
TransformClaims(claimPrincipal)
Return Task.FromResult(0)
End Function,
.RedirectToIdentityProvider = Function(context)
RedirectLogin(context)
Return Task.FromResult(0)
End Function
}
}
app.UseOpenIdConnectAuthentication(OpenIdAuthOption)
End Sub

asp.net and Identity Server 3

I am trying to authenticate my application with Identity Server Version 3. But, when I do, I get an error. Here is my code:
Startup.Auth.vb:
Partial Public Class Startup
Public Sub ConfigureAuth(app As IAppBuilder)
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType)
app.UseCookieAuthentication(New CookieAuthenticationOptions())
app.UseOpenIdConnectAuthentication(New OpenIdConnectAuthenticationOptions() With {
.ClientId = clientId,
.Authority = authority,
.RedirectUri = "https://localhost:44321/",
.Scope = OpenIdConnectScope.OpenIdProfile,
.ResponseType = OpenIdConnectResponseType.IdToken,
.TokenValidationParameters = New TokenValidationParameters() With {
.ValidateIssuer = False
},
.Notifications = New OpenIdConnectAuthenticationNotifications() With {
.AuthenticationFailed = AddressOf OnAuthenticationFailed
}
})
End Sub
Private Function OnAuthenticationFailed(ByVal context As AuthenticationFailedNotification(Of OpenIdConnectMessage, OpenIdConnectAuthenticationOptions)) As Task
context.HandleResponse()
context.Response.Redirect("/?errormessage=" & context.Exception.Message)
Return Task.FromResult(0)
End Function
end class
Login Page:
Protected Sub manuanSignIn(ByVal sender As Object, ByVal e As EventArgs) Handles manualLogin.Click
If (Not Request.IsAuthenticated) Then
Dim newAuth As AuthenticationProperties = New AuthenticationProperties()
newAuth.RedirectUri = "/"
HttpContext.Current.GetOwinContext().Authentication.Challenge(newAuth, OpenIdConnectAuthenticationDefaults.AuthenticationType)
End If
End Sub
The Error I get, when I attempt to login, is:
An existing connection was forcibly closed by the remote host
Anyone have ideas on what is causing this and how to fix it?
Adding this fixed the issue:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12

Trying to get a querystring variable with an ashx

I have been trying to sort this out all day with lots of Googling but with little effect so thanks in advance if you read and are able to help.
I have a simple page which allows a user to select files and upload to an Amazon bucket, the first page looks like this:
var checkError = false;
$(window).load(
function () {
$("#<%=FileImages.ClientID %>").fileUpload({
'fileSizeLimit': '100MB',
'uploader': 'scripts/uploader.swf',
'cancelImg': 'images/cancel.png',
'buttonText': 'Upload Files',
'script': 'UploadVB.ashx?gid=56',
'folder': 'uploads',
'multi': true,
'auto': true,
'onAllComplete': function (uploads) {
if (!checkError) {
location.href = "finished";
}
},
'onComplete': function (event, ID, fileObj, response, data) {
if (200 != parseInt(response)) {
checkError = true;
$('#FileImages' + ID).addClass('uploadifyError');
$('#FileImages' + ID + ' .percentage').text(' - ' + response);
return false;
}
}
});
}
);
Note the gid=56. It then sends the files over to UploadVB.ashx and this looks like this:
Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
Dim awsRegion As Amazon.RegionEndpoint = Amazon.RegionEndpoint.EUWest1
Dim client As New AmazonS3Client(System.Configuration.ConfigurationManager.AppSettings("AWSAccessKey").ToString(), System.Configuration.ConfigurationManager.AppSettings("AWSSecretKey").ToString(), awsRegion)
Dim fileID As String = Guid.NewGuid().ToString("N")
Dim postedFile As HttpPostedFile = context.Request.Files("Filedata")
Dim galleryid = context.Request.QueryString("gid")
Try
Dim filename As String = Path.GetFileName(postedFile.FileName)
'### I WANT TO SUBMIT THE FILENAME AND ID INTO A TABLE HERE ######
AddPortfolioPhoto(filename, Convert.ToInt16(galleryid))
'#################################################################
Dim S3_KEY As [String] = filename.Replace(" ", "")
Dim request As New PutObjectRequest()
With request
.BucketName = System.Configuration.ConfigurationManager.AppSettings("AWSBucketName").ToString()
.Key = S3_KEY
.InputStream = postedFile.InputStream
End With
client.PutObject(request)
context.Response.Write("200")
context.Response.StatusCode = 200
Catch ex As Exception
context.Response.Write("AWS ERROR :: " + ex.Message)
End Try
End Sub
Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
Get
Return False
End Get
End Property
Every time I run this above it just doesn't do anything, If I remove this line:
AddPortfolioPhoto(filename, Convert.ToInt16(galleryid))
it works great but it is crucial I get this inserted into the database someway and I just can't seem to be able to grab the gid value.
Any help is greatly appreciated.
Public Shared Sub AddPortfolioPhoto(ByVal fn As String, gid As Integer)
Dim Writer As New Data.SqlClient.SqlCommand
Writer.CommandType = Data.CommandType.StoredProcedure
Writer.CommandText = "BCMS_AddGalleryPhoto"
Writer.Connection = New Data.SqlClient.SqlConnection(System.Configuration.ConfigurationManager.AppSettings("sqlstr"))
Writer.Parameters.AddWithValue("#imgstr", Data.SqlTypes.SqlString.Null).Value = fn
Writer.Parameters.AddWithValue("#galleryid", Data.SqlTypes.SqlInt32.Null).Value = gid
Writer.Parameters.AddWithValue("#so", Data.SqlTypes.SqlInt32.Null).Value = 0
Writer.Parameters.AddWithValue("#featured", Data.SqlTypes.SqlInt32.Null).Value = 0
Writer.Prepare()
Writer.Connection.Open()
Writer.ExecuteNonQuery()
Writer.Connection.Close()
End Sub
Looks like with your help I may have gotten to the bottom of this, the value I was expecting (56) wasn't what I was actually getting, I was actually getting "uploads" in the same variable so sending a string down to this method was never going to work, thanks #matt-dot-net for suggesting and thanks Andrew Morton for the tip on dispose, I will use that rather than close.

How to return an empty object instead of null in web api

I have a web API built in .NET 4.0 and I have an issue with a simple GET request. My problem is that I want to return an object who has many properties, some strings, ints and other custom data types and in some cases some of those properties doesn't exist in the databsae so I want it to return an empy object {} and I'm just having null.
Here is some of my code
<ActionName("index")>
<HttpGet>
Public Function ObtenerAsegurado(<FromUri> rut As Integer) As Asegurado
Dim ws As New Getter2.GetterSoapClient
Dim aseg As Getter2.AseguradoDTO
aseg = ws.ObtenerAsegurado(rut)
Dim objAsegurado As Asegurado = Convertir.DTOToAsegurado(aseg)
Return objAsegurado
End Function
Public Shared Function DTOToAsegurado(asegDTO As Getter2.AseguradoDTO) As Asegurado
Dim aseg As New Asegurado
If Not asegDTO Is Nothing Then
...
aseg.cuenta = DTOToCuentas(asegDTO.Cuenta)
...
End If
Return aseg
End Function
Private Shared Function DTOToCuentas(cuentaDTO As Getter2.CuentaDTO) As Cuenta
Dim nuevacuenta As New Cuenta
If Not cuentaDTO Is Nothing AndAlso Not cuentaDTO.DescBanco Is Nothing Then
...
Else
nuevacuenta = Nothing
End If
Return nuevacuenta
End Function
As you can see, my action call to another function to make some convertion, and there i return the property of the object as nothing when there isn't present, that becomes null in the http response and I want an empty object instead {}
I also tried returning nuevacuenta = New Cuenta but that return an object with all it's properties set to nothing... Please help how can I return empty instead of null?
I found that it's doable to convert a null instance to empty object {} in JSON. C# code is there https://gist.github.com/juanonsoftware/7067ce53813201abbdae
var settings = new JsonSerializerSettings()
{
ContractResolver = new NullToEmptyObjectResolver(typeof(Child))
};
var str = JsonConvert.SerializeObject(m, settings);
class NullToEmptyObjectResolver : DefaultContractResolver
{
private readonly Type[] _types;
public NullToEmptyObjectResolver(params Type[] types)
{
_types = types;
}
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
return type.GetProperties().Select(p =>
{
var jp = base.CreateProperty(p, memberSerialization);
jp.ValueProvider = new NullToEmptyValueProvider(p, _types);
return jp;
}).ToList();
}
}
class NullToEmptyValueProvider : IValueProvider
{
readonly PropertyInfo _memberInfo;
private readonly Type[] _types;
public NullToEmptyValueProvider(PropertyInfo memberInfo, params Type[] types)
{
_memberInfo = memberInfo;
_types = types;
}
public object GetValue(object target)
{
var result = _memberInfo.GetValue(target);
if (_types.Contains(_memberInfo.PropertyType) && result == null)
{
result = new object();
}
return result;
}
public void SetValue(object target, object value)
{
_memberInfo.SetValue(target, value);
}
}
I'm not sure if this is the problem, but I think it could be the way in which you are testing for nothing?
<ActionName("index")>
<HttpGet>
Public Function ObtenerAsegurado(<FromUri> rut As Integer) As Asegurado
'
Dim ws As New Getter2.GetterSoapClient
Dim aseg As Getter2.AseguradoDTO
'
aseg = ws.ObtenerAsegurado(rut)
Dim objAsegurado As Asegurado = Convertir.DTOToAsegurado(aseg)
Return objAsegurado
'
End Function
'
Public Shared Function DTOToAsegurado(asegDTO As Getter2.AseguradoDTO) As Asegurado
'
Dim aseg As New Asegurado
If (asegDTO Is Nothing) = False Then
'...
aseg.cuenta = DTOToCuentas(asegDTO.Cuenta)
'...
End If
Return aseg
'
End Function
'
Private Shared Function DTOToCuentas(cuentaDTO As Getter2.CuentaDTO) As Cuenta
'
Dim nuevacuenta As New Cuenta
If (cuentaDTO Is Nothing) = False And (cuentaDTO.DescBanco Is Nothing) = False Then
'...
Else
nuevacuenta = Nothing
End If
Return nuevacuenta
'
End Function

Using OWIN with VB

I am trying to set up some password policies, I managed to successfully do this in C#, but I need to convert the code into VB. There are two issues that I cannot figure out:
1) app.UseUserManagerFactory does not exist;
It states UseUserManagerFactory is not a member of Owin.IAppBuilder
2) The OnCreate attribute when instantiating the Provider is not being passed correctly
Public Sub ConfigureAuth(app As IAppBuilder)
'Configure the UserManager
app.UseUserManagerFactory(New IdentityFactoryOptions(Of ApplicationUserManager)() With { _
.DataProtectionProvider = app.GetDataProtectionProvider(), _
.Provider = New IdentityFactoryProvider(Of ApplicationUserManager)() With { _
.OnCreate = ApplicationUserManager.Create _
} _
})
Here is the Create function for the sake of completeness:
Public Shared Function Create(options As IdentityFactoryOptions(Of ApplicationUserManager))
Dim manager = New ApplicationUserManager(New ApplicationUserStore(New ApplicationDbContext()))
manager.UserValidator = New UserValidator(Of ApplicationUser)(manager) With {.AllowOnlyAlphanumericUserNames = False, .RequireUniqueEmail = True}
manager.PasswordValidator = New PasswordValidator()
Dim dataProtectionProvider = options.DataProtectionProvider
If (dataProtectionProvider IsNot Nothing) Then
' Do stuff
End If
Return manager
End Function
Any help would be appreciated, my VB skills coupled with the lack of documentation has me scratching my head.

Resources