i am migrating my SSRS deployed on Azure SQL reporting to SSRS hosted on Azure VM. I have successfully created a VM and deployed my reports, which can be viewed from browser. now my requirement is that i want to get the reports in PDF or EXCEL format programatically. that requirment working fine for last one year but as i moved to VM when i called
ReportViewer.ServerReport.GetParameters()
method it throw an exception 401 UnAuthorized access. i am currently using below class to get authenticate my user to get reports in PDF or EXCEl
public class SSRSReportServerCredentials : IReportServerCredentials
{
public SSRSReportServerCredentials()
{
}
public WindowsIdentity ImpersonationUser
{
get { return null; }
}
public ICredentials NetworkCredentials
{
get { return null; }
}
public bool GetFormsCredentials(out Cookie authCookie, out string user, out string password, out string authority)
{
authCookie = null;
user = sa;
password = test;
authority = SERVER.reporting.windows.net;
return true;
}
}
Can any one help me out to fix my production issue.
best regards,
Zeeshan
sorry guys for too much late reply, i have fixed that issue almost 2 months ago but unable to find time to share my findings with you all. i have change the credential file as below and call the parametrize constructor
public class SSRSReportServerCredentials : IReportServerCredentials
{
public SSRSReportServerCredentials()
{
}
public WindowsIdentity ImpersonationUser
{
get { return null; }
}
public ICredentials NetworkCredentials
{
get { return new NetworkCredential(WebConfigurationManager.AppSettings["userName"], WebConfigurationManager.AppSettings["password"]); }
}
public bool GetFormsCredentials(out Cookie authCookie, out string user, out string password, out string authority)
{
authCookie = null;
user = null;
password = null;
authority = null;
return false;
}
}
Related
I am using below code to log out the the current logged in user
public async Task Logout()
{
SecureStorage.RemoveAll();
await RealmMain.realmApp.CurrentUser.LogOutAsync();
}
Then, I use below code to sign in back again.
public async Task<bool> LoginWithCredential(Action<string> error)
{
try {
var credentials = Credentials.EmailPassword(userId, pass);
var user = await RealmMain.realmApp.LogInAsync(credentials);
return user != null;
}
catch (Exception ex){
SecureStorage.RemoveAll();
Console.WriteLine(ex);
error(exceptionText);
return false;
}
}
RealmMain Class is like this below.
public sealed class RealmMain
{
private const string AppId = "*************";
public static App realmApp = App.Create(AppId);
public SyncConfiguration ConfigForSync
{
get
{
var temp = new SyncConfiguration(realmApp.CurrentUser.Id, realmApp.CurrentUser)
{
// EncryptionKey = AppContext.GetBytes(AppContext.DbKey)
};
Console.WriteLine(temp.EncryptionKey);
return temp;
}
}
public static RealmMain Instance { get; } = new RealmMain();
private RealmMain()
{
}
}
Problem here is - When is log out and then try to sign in with the same user credential.
I get below error.
"Realms.Sync.Exceptions.AppException: Unknown: must authenticate first
at Realms.Sync.App.LogInAsync (Realms.Sync.Credentials credentials)"
If I use some different user to sign in after logging out.
I get this.
In nutshell Logout and then login is not working for me, I have to quit the app to make it work every time.
Any suggestion to solve this issue would be appreciated.
I am trying to send permissions for documentdb for a specific user from my azure server to my client app, which are xamarin forms.
On server side everything looks good and I can see users specific permissions and token.
But when permissions are received in the client, the token is stripped away, why?
I am new with documentdb so hopefully it is just me.
I am using an Azure Mobile App service as backend.
My backend controller returns an object holding properties for documentdb database including a list of permissions for the user.
public class DbConfig
{
public string DatabaseName { get; set; }
public string CollectionId { get; set; }
public string EndpointUri { get; set; }
public IList<Permission> Permissions { get; set; }
}
I create a permission for a user for the entire collection if not already created.
public async Task<Permission> CreatePermissionAsync(string resourceLink, string userLink, PermissionMode mode, string resourcePartitionKey = null)
{
try
{
Permission permission = new Permission
{
Id = Guid.NewGuid().ToString("N"),
PermissionMode = mode,
ResourceLink = resourceLink
};
if (resourcePartitionKey != null)
{
permission.ResourcePartitionKey = new PartitionKey(resourcePartitionKey);
}
var result = await client.CreatePermissionAsync(userLink, permission);
DbConfig.Permissions.Add(result);
return result;
}
catch (Exception e)
{
Trace.WriteLine($"##### Exception: {e}");
throw;
}
}
I retrieve permissions for a user with this method.
public List<Permission> GetPermissionsForUserPermissionLink(User user)
{
var permFeed = client.CreatePermissionQuery(user.PermissionsLink);
List<Permission> permList = new List<Permission>();
foreach (Permission perm in permFeed)
{
permList.Add(perm);
DbConfig.Permissions.Add(perm);
}
return permList;
}
On the client side in my Xamarin forms app i use this call to my custom controller in the backend.
var parameters = new Dictionary<string, string> { { "userid", Settings.AzureUserId } };
dbConfig = await client.InvokeApiAsync<DbConfig>("Settings", HttpMethod.Get, parameters);
When i look at the permissionlist in the dbConfig object the token for a permission is null. My thought was that I could instantiate a documentdb client based on the permissionslist but it fails.
public void CreateDocumentDbClient(DbConfig config)
{
client = new DocumentClient(new Uri(config.EndPointUri), config.Permissions);
collectionLink = UriFactory.CreateDocumentCollectionUri(config.DatabaseName, config.CollectionId);
IsInitialized = true;
}
EDITS MADE FROM ANSWER
Just for finish up upon question.
I created a custom class holding both Permission and Token
public class PermissionCustom
{
public Permission Permission { get; set; }
public string Token { get; set; }
}
This makes it possible to create a documentdb client like this:
client = new DocumentClient(new Uri(config.EndPointUri), config.Permissions[0].Token);
So far so good :-) but it doesn't makes it easier to secure your database considering users could have many permissions for different resources. Even though it is properly to make it more secure, the token is readonly in the first place.
According to your code, I have checked this issue and found I could encounter the same issue. When you invoke client.InvokeApiAsync<DbConfig>("Settings", HttpMethod.Get, parameters);, you would send request with the following link:
https://{your-app-name}.azurewebsites.net/api/settings?userid={Settings.AzureUserId}
By using fiddler you could find that the token has been sent to your mobile client as follows:
But when deserialize it to Permission, the token has not been initialized correctly. I found that the token property is read only as follows:
In summary, I recommend that you need to define your custom Permission class and refer to the Permission class provided by DocumentDB client SDK for defining the properties you need within your custom permission class in your mobile client.
I have registered two apps(app target as 'Test') on Exact online,redirect url for one of these application is azure hosted site and other with locally hosted site.
App with locally hosted site authorizes properly and returns token successfully.
however,it fails to authorize app with azure hosted site.
OAuth2 ProtocolVersion is V20.
Can anybody help with this?
Do we need to do some settings on azure portal for Oauth2 authentication for third party software's like Exact online in this case,to get request authorized properly?
Thanks in advance.
Code sample:
region Authorize request
private static readonly ExactOnlineOAuthClient OAuthClient = new ExactOnlineOAuthClient();
private Boolean AuthorizeClient()
{
OAuthClient.Authorize(returnUri);
return (OAuthClient.Authorization != null);
}
#endregion
#region ExactOnlineOAuthClient Class
public ExactOnlineOAuthClient()
: base(CreateAuthorizationServerDescription(), ClientIdentifier(), ClientSecret())
{
ClientCredentialApplicator = ClientCredentialApplicator.PostParameter(ClientSecret());
}
private static AuthorizationServerDescription CreateAuthorizationServerDescription()
{
var baseUri = "https://start.exactonline.nl";
var uri = new Uri(baseUri.EndsWith("/") ? baseUri : baseUri + "/");
var serverDescription = new AuthorizationServerDescription
{
AuthorizationEndpoint = new Uri(uri, "api/oauth2/auth"),
TokenEndpoint = new Uri(uri, "api/oauth2/token")
};
return serverDescription;
}
private static string ClientIdentifier()
{
return "ClientIdentifier"; //valid client id
}
private static string ClientSecret()
{
return "ClientSecret"; //valid client secret
}
private void Authorize(Uri returnUri)
{
try
{
if (Authorization == null)
{
Authorization = ProcessUserAuthorization();
if (Authorization == null)
{
// Kick off authorization request
RequestUserAuthorization(null, returnUri);
}
}
else
{
if (AccessTokenHasToBeRefreshed())
{
RefreshAuthorization(Authorization);
}
}
}
catch(Exception ex)
{
}
}
#endregion
I have an application that I'd like to expose to as many users as possible. To accomplish this I'm following the directions as explained here to connect my app to Azure Active Directory and a variation of these instructions to connect AAD to Azure ACS 2.0.
Azure ACS 2.0 will handle all the federated domains, and Microsoft Accounts (formerly LiveID or Passport). It will also handle Facebook, Twitter, and other OAuth services.
Azure Active directory will handle Office 365, and anyone who is syncing their corporate Active Directory to the cloud.
My home realm discovery page will issue a GET at the following URL to determine if the LiveID or AzureAD domain should be used.
https://login.microsoftonline.com/GetUserRealmExtended.srf?login=EMAIL#COMPANY.com
or
http://odc.officeapps.live.com/odc/emailhrd/getidp?hm=0&emailAddress=USER%COMPANY.com
If the user doesn't exist, I'll use Azure ACS with a federation to that company. Lacking that, the user won't be able to log in.
Now that I explained my configuration, I intend to have Windows Identity Foundation (WIF) to allow authentications from both ACS 2.0 and ADFS.
Question
How do I get WIF 4.5, and specifically the ValidatingIssuerNameRegistry to properly handle multiple trusts to multiple IDPs?
Below is code that comes with VS2013 when federating an application with Azure Active Directory. It responds to all federation requests and does other things that I don't understand. Any links or information on this class would be helpful
public class DatabaseIssuerNameRegistry : ValidatingIssuerNameRegistry
{
public static bool ContainsTenant(string tenantId)
{
using (TenantDbContext context = new TenantDbContext())
{
return context.Tenants
.Where(tenant => tenant.Id == tenantId)
.Any();
}
}
public static bool ContainsKey(string thumbprint)
{
using (TenantDbContext context = new TenantDbContext())
{
return context.IssuingAuthorityKeys
.Where(key => key.Id == thumbprint)
.Any();
}
}
public static void RefreshKeys(string metadataLocation)
{
IssuingAuthority issuingAuthority = ValidatingIssuerNameRegistry.GetIssuingAuthority(metadataLocation);
bool newKeys = false;
foreach (string thumbprint in issuingAuthority.Thumbprints)
{
if (!ContainsKey(thumbprint))
{
newKeys = true;
break;
}
}
if (newKeys)
{
using (TenantDbContext context = new TenantDbContext())
{
context.IssuingAuthorityKeys.RemoveRange(context.IssuingAuthorityKeys);
foreach (string thumbprint in issuingAuthority.Thumbprints)
{
context.IssuingAuthorityKeys.Add(new IssuingAuthorityKey { Id = thumbprint });
}
context.SaveChanges();
}
}
}
public static bool TryAddTenant(string tenantId, string signupToken)
{
if (!ContainsTenant(tenantId))
{
using (TenantDbContext context = new TenantDbContext())
{
SignupToken existingToken = context.SignupTokens.Where(token => token.Id == signupToken).FirstOrDefault();
if (existingToken != null)
{
context.SignupTokens.Remove(existingToken);
context.Tenants.Add(new Tenant { Id = tenantId });
context.SaveChanges();
return true;
}
}
}
return false;
}
public static void AddSignupToken(string signupToken, DateTimeOffset expirationTime)
{
using (TenantDbContext context = new TenantDbContext())
{
context.SignupTokens.Add(new SignupToken
{
Id = signupToken,
ExpirationDate = expirationTime
});
context.SaveChanges();
}
}
public static void CleanUpExpiredSignupTokens()
{
DateTimeOffset now = DateTimeOffset.UtcNow;
using (TenantDbContext context = new TenantDbContext())
{
IQueryable<SignupToken> tokensToRemove = context.SignupTokens.Where(token => token.ExpirationDate <= now);
if (tokensToRemove.Any())
{
context.SignupTokens.RemoveRange(tokensToRemove);
context.SaveChanges();
}
}
}
protected override bool IsThumbprintValid(string thumbprint, string issuer)
{
string issuerID = issuer.TrimEnd('/').Split('/').Last();
return ContainsTenant(issuerID) &&
ContainsKey(thumbprint);
}
}
Vittorio Bertocci does a good job of explaining the DatabaseIssuerNameRegistry in this post.
VS2013 RTM, Organizational Accounts and Publishing to Windows Azure Web Sites!
The bottom line is that DatabaseIssuerNameRegistry is just an Entity Framework based ValidatingIssuerNameRegistry that looks up the issuer name from a database using the the thumbprint of the token and verifies that it matches the configured value for the Issuer name, as opposed to using the web.config.It is more flexible and handles updating thumbprints if/when the authority changes them.
I have the following code inside MyDataService.svc.cs (This is an example from DevExpress):
namespace MyDataService {
[System.ServiceModel.ServiceBehavior(IncludeExceptionDetailInFaults = true)]
[JSONPSupportBehavior]
public class DataService : DataService<TestDataEntities>, IServiceProvider {
public static void InitializeService(DataServiceConfiguration config) {
config.SetEntitySetAccessRule("*", EntitySetRights.AllRead);
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3;
}
public object GetService(Type serviceType) {
if (serviceType == typeof(IDataServiceStreamProvider)) {
return new ImageStreamProvider();
}
return null;
}
protected override void OnStartProcessingRequest(ProcessRequestArgs args) {
CustomBasicAuth.Authenticate(HttpContext.Current);
if (HttpContext.Current.User == null)
throw new DataServiceException(401, "Invalid login or password");
base.OnStartProcessingRequest(args);
}
}
}
So while this is will check the Entity for a username and password, how safe is it that config.SetEntitySetAccessRule is set to AllRead. Wouldn't someone just be able to see this information on a url such as www.website.com/MyDataService.svc/Customer (where Customer is the table). If this is not so can someone please fill in the conceptual gap I am facing. Thanks!
You are correct that all entities will be returned when queried - AllRead just disallows insert updates and deletes.
You will need to use Query Interceptor to add your logic to restrict users to the set of data they have permission to view, for example adding a check user id to the query.